public void appendPath(APath path)
        {
            int[] tempmoves = new int[pathlen + path.pathlen];
            int i;
            
            for (i = 0; i < pathlen+path.pathlen; i++)
                tempmoves[i] = (i < pathlen) ? amoves[i] : path.amoves[i - pathlen];

            amoves = tempmoves;
            pathlen += path.pathlen;
        }
        public void appendPath(APath path)
        {
            int[] tempmoves = new int[pathlen + path.pathlen];
            int   i;

            for (i = 0; i < pathlen + path.pathlen; i++)
            {
                tempmoves[i] = (i < pathlen) ? amoves[i] : path.amoves[i - pathlen];
            }

            amoves   = tempmoves;
            pathlen += path.pathlen;
        }
        // fill the task queue with a number of moves
        // to follow a certain path
        public void path2QueueTasks(APath path, int corientation)
        {
            int i;
            int curOrient = corientation;

            for (i = 0; i < path.pathlen; i++)
            {
                switch (curOrient)
                {
                case orNORTH:
                    switch (path.amoves[i])
                    {
                    case APath.instGO_NORTH:
                        insertTask(taskGO_FORWARD);
                        break;

                    case APath.instGO_EAST:
                        insertTask(taskTURN_RIGHT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orEAST;
                        break;

                    case APath.instGO_SOUTH:
                        insertTask(taskGO_BACKWARD);
                        break;

                    case APath.instGO_WEST:
                        insertTask(taskTURN_LEFT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orWEST;
                        break;
                    }
                    break;

                case orEAST:
                    switch (path.amoves[i])
                    {
                    case APath.instGO_NORTH:
                        insertTask(taskTURN_LEFT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orNORTH;
                        break;

                    case APath.instGO_EAST:
                        insertTask(taskGO_FORWARD);
                        break;

                    case APath.instGO_SOUTH:
                        insertTask(taskTURN_RIGHT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orSOUTH;
                        break;

                    case APath.instGO_WEST:
                        insertTask(taskGO_BACKWARD);
                        break;
                    }
                    break;

                case orSOUTH:
                    switch (path.amoves[i])
                    {
                    case APath.instGO_NORTH:
                        insertTask(taskGO_BACKWARD);
                        break;

                    case APath.instGO_EAST:
                        insertTask(taskTURN_LEFT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orEAST;
                        break;

                    case APath.instGO_SOUTH:
                        insertTask(taskGO_FORWARD);
                        break;

                    case APath.instGO_WEST:
                        insertTask(taskTURN_RIGHT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orWEST;
                        break;
                    }
                    break;

                case orWEST:
                    switch (path.amoves[i])
                    {
                    case APath.instGO_NORTH:
                        insertTask(taskTURN_RIGHT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orNORTH;
                        break;

                    case APath.instGO_EAST:
                        insertTask(taskGO_BACKWARD);
                        break;

                    case APath.instGO_SOUTH:
                        insertTask(taskTURN_LEFT);
                        insertTask(taskGO_FORWARD);
                        curOrient = orSOUTH;
                        break;

                    case APath.instGO_WEST:
                        insertTask(taskGO_FORWARD);
                        break;
                    }
                    break;
                }
            }

            insertTask(taskHUG);
        }
        public void planner()
        {
            int i, j;

            if ((mappingFSM.ipos != LastKnownCartIpos) || (mappingFSM.jpos != LastKnownCartJpos))
            {
                // the mobile robot has changed position,
                // thus we may need to follow a different path to get to it

                // updating last known cart position
                LastKnownCartIpos = mappingFSM.ipos;
                LastKnownCartJpos = mappingFSM.jpos;

                // finding the closest reachable cell next to the cart

                int   minpathlen = 1000000, mini, minj;
                APath minpath = null;

                for (i = 0; i < mappingFSM.MapDim; i++)
                {
                    for (j = 0; j < mappingFSM.MapDim; j++)
                    {
                        if (mappingFSM.Map[i][j] == cellVOID)
                        {
                            if (isNeighborCart(i, j))
                            {
                                Boolean pfound    = false;
                                APath   path2cell = shortestPath(ipos, jpos, i, j, null, 0, ref pfound);
                                if (pfound)
                                {
                                    if (minpathlen > path2cell.pathlen)
                                    {
                                        minpathlen = path2cell.pathlen;
                                        minpath    = path2cell;
                                        mini       = i;
                                        minj       = j;
                                    }
                                }
                            }
                        }
                    }
                }
                // clearing the task queue anyway
                TaskQueueLength = 0;

                if (minpath == null) // no path close to the cell found
                // adding a reaction
                {
                    insertTask(taskDISSAPOINTED);
                }
                else // planning to move to the cell
                {
                    path2QueueTasks(minpath, orientation);
                }
            }
            else
            if ((!close2Cart()) && (TaskQueueLength == 0))
            {
                // finding the closest reachable cell next to the cart

                int   minpathlen = 1000000, mini, minj;
                APath minpath = null;

                for (i = 0; i < mappingFSM.MapDim; i++)
                {
                    for (j = 0; j < mappingFSM.MapDim; j++)
                    {
                        if (mappingFSM.Map[i][j] == cellVOID)
                        {
                            if (isNeighborCart(i, j))
                            {
                                Boolean pfound    = false;
                                APath   path2cell = shortestPath(ipos, jpos, i, j, null, 0, ref pfound);
                                if (pfound)
                                {
                                    if (minpathlen > path2cell.pathlen)
                                    {
                                        minpathlen = path2cell.pathlen;
                                        minpath    = path2cell;
                                        mini       = i;
                                        minj       = j;
                                    }
                                }
                            }
                        }
                    }
                }
                // clearing the task queue anyway
                TaskQueueLength = 0;

                if (minpath == null)     // no path close to the cell found
                // adding a reaction
                {
                    insertTask(taskDISSAPOINTED);
                }
                else     // planning to move to the cell
                {
                    path2QueueTasks(minpath, orientation);
                }
            }
        }
        // an A* shortest path algorithm
        public APath shortestPath(int startIpos, int startJpos, int destIpos, int destJpos,
                                  MapCell[] Visited, int VisitedLength, ref Boolean PathFound)
        {
            int i;
            int newVisitedLength = VisitedLength + 1;

            MapCell[] newVisited   = new MapCell[newVisitedLength];
            APath     shortestpath = null;

            // first checking whether we are in /out of map bounds
            if ((startIpos < 0) || (startIpos >= mappingFSM.MapDim) || (startJpos < 0) || (startJpos >= mappingFSM.MapDim))
            {
                PathFound = false;
            }
            else
            if (mappingFSM.Map[startIpos][startJpos] == MappingFSM.cellBLOCK)
            {
                PathFound = false;
            }
            else
            if (inPath(startIpos, startJpos, Visited, VisitedLength))
            {
                PathFound = false;
            }
            else if ((mappingFSM.ipos == startIpos) && (mappingFSM.jpos == startJpos))
            {
                PathFound = false;
            }
            else
            {
                // copying map of visited cells
                for (i = 0; i < VisitedLength; i++)
                {
                    newVisited[i] = Visited[i];
                }
                // visited cells list copied
                // now adding current position
                newVisited[newVisitedLength - 1].ipos = startIpos;
                newVisited[newVisitedLength - 1].jpos = startJpos;
                // checking northern cell
                if ((startIpos - 1 == destIpos) && (startJpos == destJpos))
                {
                    PathFound              = true;
                    shortestpath           = new APath(1);
                    shortestpath.amoves[0] = APath.instGO_NORTH;
                }         // checking eastern cell
                else if ((startIpos == destIpos) && (startJpos + 1 == destJpos))
                {
                    PathFound              = true;
                    shortestpath           = new APath(1);
                    shortestpath.amoves[0] = APath.instGO_EAST;
                }         // checking southern cell
                else if ((startIpos + 1 == destIpos) && (startJpos == destJpos))
                {
                    PathFound              = true;
                    shortestpath           = new APath(1);
                    shortestpath.amoves[0] = APath.instGO_SOUTH;
                }        // checking western cell
                else if ((startIpos == destIpos) && (startJpos - 1 == destJpos))
                {
                    PathFound              = true;
                    shortestpath           = new APath(1);
                    shortestpath.amoves[0] = APath.instGO_WEST;
                }        // recursively checking paths now...
                else
                {
                    // sorting out euclidean distances of neighboring cells
                    double[] distances = new double[4];         // 0-north, 1-east, 2-south, 3-west
                    for (i = 0; i < 4; i++)
                    {
                        distances[i] = Math.Sqrt(Math.Pow((double)(startIpos - destIpos), 2) + Math.Pow((double)(startJpos - destJpos), 2));
                    }
                    // now repeating until we find a valid path
                    Boolean pfound = false;
                    PathFound = false;
                    int    counter          = 0;
                    double mindistance      = 100000;
                    int    mindistanceindex = 0;
                    APath  newpath;
                    while ((!pfound) && (counter < 4))
                    {
                        mindistance = 100000;         // large enough value for minimum euclidean distance
                        for (i = 0; i < 4; i++)
                        {
                            if ((distances[i] < mindistance) && (distances[i] >= 0))
                            {
                                mindistance      = distances[i];
                                mindistanceindex = i;
                            }
                        }
                        if (mindistance < 100000)
                        {
                            distances[mindistanceindex] = -1;

                            switch (mindistanceindex)
                            {
                            case 0:             // North
                                newpath = shortestPath(startIpos - 1, startJpos, destIpos, destJpos,
                                                       newVisited, newVisitedLength, ref pfound);
                                if (pfound)
                                {
                                    PathFound              = true;
                                    shortestpath           = new APath(1);
                                    shortestpath.amoves[0] = APath.instGO_NORTH;
                                    shortestpath.appendPath(newpath);
                                }
                                break;

                            case 1:             // East
                                newpath = shortestPath(startIpos, startJpos + 1, destIpos, destJpos,
                                                       newVisited, newVisitedLength, ref pfound);
                                if (pfound)
                                {
                                    PathFound              = true;
                                    shortestpath           = new APath(1);
                                    shortestpath.amoves[0] = APath.instGO_EAST;
                                    shortestpath.appendPath(newpath);
                                }
                                break;

                            case 2:             // South
                                newpath = shortestPath(startIpos + 1, startJpos, destIpos, destJpos,
                                                       newVisited, newVisitedLength, ref pfound);
                                if (pfound)
                                {
                                    PathFound              = true;
                                    shortestpath           = new APath(1);
                                    shortestpath.amoves[0] = APath.instGO_SOUTH;
                                    shortestpath.appendPath(newpath);
                                }
                                break;

                            case 3:             // South
                                newpath = shortestPath(startIpos, startJpos - 1, destIpos, destJpos,
                                                       newVisited, newVisitedLength, ref pfound);
                                if (pfound)
                                {
                                    PathFound              = true;
                                    shortestpath           = new APath(1);
                                    shortestpath.amoves[0] = APath.instGO_WEST;
                                    shortestpath.appendPath(newpath);
                                }
                                break;
                            }
                        }
                        counter++;
                    }
                }     // recursion else ends
            }         // big else ends

            return(shortestpath);
        }
        // an A* shortest path algorithm
        public APath shortestPath(int startIpos, int startJpos, int destIpos, int destJpos,
                                 MapCell[] Visited, int VisitedLength, ref Boolean PathFound)
        {
            int i;
            int newVisitedLength = VisitedLength + 1;
            MapCell[] newVisited = new MapCell[newVisitedLength];
            APath shortestpath = null;
            // first checking whether we are in /out of map bounds
            if ((startIpos < 0) || (startIpos >= mappingFSM.MapDim) || (startJpos < 0) || (startJpos >= mappingFSM.MapDim))
                PathFound = false;
            else
                if (mappingFSM.Map[startIpos][startJpos] == MappingFSM.cellBLOCK)
                    PathFound = false;
                else
                    if (inPath(startIpos, startJpos, Visited, VisitedLength))
                        PathFound = false;
                    else if ((mappingFSM.ipos == startIpos) && (mappingFSM.jpos == startJpos))
                        PathFound = false;
                    else
                    {

                        // copying map of visited cells
                        for (i = 0; i < VisitedLength; i++)
                            newVisited[i] = Visited[i];
                        // visited cells list copied
                        // now adding current position
                        newVisited[newVisitedLength - 1].ipos = startIpos;
                        newVisited[newVisitedLength - 1].jpos = startJpos;
                        // checking northern cell
                        if ((startIpos - 1 == destIpos) && (startJpos == destJpos))
                        {
                            PathFound = true;
                            shortestpath = new APath(1);
                            shortestpath.amoves[0] = APath.instGO_NORTH;
                        } // checking eastern cell
                        else if ((startIpos == destIpos) && (startJpos + 1 == destJpos))
                        {
                            PathFound = true;
                            shortestpath = new APath(1);
                            shortestpath.amoves[0] = APath.instGO_EAST;
                        } // checking southern cell
                        else if ((startIpos + 1 == destIpos) && (startJpos == destJpos))
                        {
                            PathFound = true;
                            shortestpath = new APath(1);
                            shortestpath.amoves[0] = APath.instGO_SOUTH;
                        }// checking western cell
                        else if ((startIpos == destIpos) && (startJpos - 1 == destJpos))
                        {
                            PathFound = true;
                            shortestpath = new APath(1);
                            shortestpath.amoves[0] = APath.instGO_WEST;
                        }// recursively checking paths now...
                        else
                        {
                            // sorting out euclidean distances of neighboring cells
                            double[] distances = new double[4]; // 0-north, 1-east, 2-south, 3-west
                            for (i = 0; i < 4; i++)
                                distances[i] = Math.Sqrt(Math.Pow((double)(startIpos - destIpos), 2) + Math.Pow((double)(startJpos - destJpos), 2));
                            // now repeating until we find a valid path
                            Boolean pfound = false;
                            PathFound = false;
                            int counter = 0;
                            double mindistance = 100000;
                            int mindistanceindex = 0;
                            APath newpath;
                            while ((!pfound) && (counter < 4))
                            {
                                mindistance = 100000; // large enough value for minimum euclidean distance
                                for (i = 0; i < 4; i++)
                                    if ((distances[i] < mindistance) && (distances[i] >= 0))
                                    {
                                        mindistance = distances[i];
                                        mindistanceindex = i;
                                    }
                                if (mindistance < 100000)
                                {
                                    distances[mindistanceindex] = -1;

                                    switch (mindistanceindex)
                                    {
                                        case 0: // North
                                            newpath = shortestPath(startIpos - 1, startJpos, destIpos, destJpos,
                                                newVisited, newVisitedLength, ref pfound);
                                            if (pfound)
                                            {
                                                PathFound = true;
                                                shortestpath = new APath(1);
                                                shortestpath.amoves[0] = APath.instGO_NORTH;
                                                shortestpath.appendPath(newpath);
                                            }
                                            break;
                                        case 1: // East
                                            newpath = shortestPath(startIpos, startJpos + 1, destIpos, destJpos,
                                                newVisited, newVisitedLength, ref pfound);
                                            if (pfound)
                                            {
                                                PathFound = true;
                                                shortestpath = new APath(1);
                                                shortestpath.amoves[0] = APath.instGO_EAST;
                                                shortestpath.appendPath(newpath);
                                            }
                                            break;
                                        case 2: // South
                                            newpath = shortestPath(startIpos + 1, startJpos, destIpos, destJpos,
                                                newVisited, newVisitedLength, ref pfound);
                                            if (pfound)
                                            {
                                                PathFound = true;
                                                shortestpath = new APath(1);
                                                shortestpath.amoves[0] = APath.instGO_SOUTH;
                                                shortestpath.appendPath(newpath);
                                            }
                                            break;
                                        case 3: // South
                                            newpath = shortestPath(startIpos, startJpos - 1, destIpos, destJpos,
                                                newVisited, newVisitedLength, ref pfound);
                                            if (pfound)
                                            {
                                                PathFound = true;
                                                shortestpath = new APath(1);
                                                shortestpath.amoves[0] = APath.instGO_WEST;
                                                shortestpath.appendPath(newpath);
                                            }
                                            break;
                                    }

                                }
                                counter++;
                            }
                        } // recursion else ends
                    } // big else ends

            return shortestpath;
        }
        // fill the task queue with a number of moves
        // to follow a certain path
        public void path2QueueTasks(APath path, int corientation)
        {
            int i;
            int curOrient = corientation;

            for (i = 0; i < path.pathlen; i++)
                switch (curOrient)
                {
                    case orNORTH:
                        switch (path.amoves[i])
                        {
                            case APath.instGO_NORTH:
                                insertTask(taskGO_FORWARD);
                                break;
                            case APath.instGO_EAST:
                                insertTask(taskTURN_RIGHT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orEAST;
                                break;
                            case APath.instGO_SOUTH:
                                insertTask(taskGO_BACKWARD);
                                break;
                            case APath.instGO_WEST:
                                insertTask(taskTURN_LEFT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orWEST;
                                break;
                        }
                        break;
                    case orEAST:
                        switch (path.amoves[i])
                        {
                            case APath.instGO_NORTH:
                                insertTask(taskTURN_LEFT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orNORTH;
                                break;
                            case APath.instGO_EAST:
                                insertTask(taskGO_FORWARD);
                                break;
                            case APath.instGO_SOUTH:
                                insertTask(taskTURN_RIGHT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orSOUTH;
                                break;
                            case APath.instGO_WEST:
                                insertTask(taskGO_BACKWARD);
                                break;
                        }
                        break;
                    case orSOUTH:
                        switch (path.amoves[i])
                        {
                            case APath.instGO_NORTH:
                                insertTask(taskGO_BACKWARD);
                                break;
                            case APath.instGO_EAST:
                                insertTask(taskTURN_LEFT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orEAST;
                                break;
                            case APath.instGO_SOUTH:
                                insertTask(taskGO_FORWARD);
                                break;
                            case APath.instGO_WEST:
                                insertTask(taskTURN_RIGHT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orWEST;
                                break;
                        }
                        break;
                    case orWEST:
                        switch (path.amoves[i])
                        {
                            case APath.instGO_NORTH:
                                insertTask(taskTURN_RIGHT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orNORTH;
                                break;
                            case APath.instGO_EAST:
                                insertTask(taskGO_BACKWARD);
                                break;
                            case APath.instGO_SOUTH:
                                insertTask(taskTURN_LEFT);
                                insertTask(taskGO_FORWARD);
                                curOrient = orSOUTH;
                                break;
                            case APath.instGO_WEST:
                                insertTask(taskGO_FORWARD);
                                break;
                        }
                        break;
                }

            insertTask(taskHUG);
        }