/// <summary>
        /// Selects the south-western voxel of the point selected by the mouse.
        /// The loc parameter and the ab parameter should point to the same location.
        /// </summary>
        private Location selectVoxel(MapViewWindow view, Location loc, Point ab)
        {
            // top-left corner of the selected location
            Point vxl = World.world.fromXYZToAB(loc);

            Point offset = new Point(ab.X - vxl.X, ab.Y - vxl.Y);

            if (offset.X < 8)
            {
                loc.x--;
            }
            else
            if (offset.X >= 24)
            {
                loc.y++;
            }
            else
            {
                MountainVoxel mv = MountainVoxel.get(loc);
                int           h0 = (mv != null)?(int)mv.getHeight(Direction.NORTHEAST):0;
                int           h2 = (mv != null)?(int)mv.getHeight(Direction.SOUTHWEST):0;

                if (offset.Y >= (16 - (h0 + h2) * 4) / 2)
                {
                    loc.x--; loc.y++;
                }
            }

            return(loc);
        }
        private int getHeight(Location loc, Direction d)
        {
            MountainVoxel mv = MountainVoxel.get(loc);

            if (mv != null)
            {
                return(mv.getHeight(d) + loc.z * 4);
            }
            else
            {
                return(loc.z * 4);
            }
        }
        /// <summary>
        /// Lowers the north-eastern corner of the specified voxel.
        /// </summary>
        /// <returns>false if the operation was unsuccessful.</returns>
        private bool lower(Location loc)
        {
            World world = World.world;

            if (!canBeLowered(ref loc))
            {
                return(false);
            }


            // then actually change the terrain
            for (int x = 0; x <= 1; x++)
            {
                for (int y = -1; y <= 0; y++)
                {
                    Location  l = new Location(loc.x + x, loc.y + y, loc.z);
                    Direction d = Direction.get(1 - x * 2, -y * 2 - 1);                 // corner to modify

                    MountainVoxel mv = MountainVoxel.get(l);
                    if (mv == null)
                    {
                        World.world.lowerGround(l);
                        mv = new MountainVoxel(l, 4, 4, 4, 4);
                    }

                    mv.setHeight(d, mv.getHeight(d) - 1);

                    if (mv.isFlattened)                         // completely flattened
                    {
                        world.remove(mv);
                    }
                }
            }

            return(true);
        }
        // clean it up by using MountainVoxel.isCornerMatched
        private bool canBeLowered(ref Location loc)
        {
            World world = World.world;

            if (!isFourAdjacentCornersMatched(loc))
            {
                return(false);
            }

            MountainVoxel mvBase = MountainVoxel.get(loc);

            if (mvBase != null)
            {
                if (mvBase.getHeight(Direction.NORTHEAST) == 0)
                {
                    return(false);                      // other corners need to be lowered first.
                }
            }
            else
            {
                int glevel = world.getGroundLevel(loc);
                if (glevel != loc.z && glevel != loc.z - 1)
                {
                    return(false);
                }
                if (loc.z == 0)
                {
                    return(false);                      // can't dig deeper
                }
                loc.z--;
            }

            // check other voxels
            for (int x = 0; x <= 1; x++)
            {
                for (int y = -1; y <= 0; y++)
                {
                    Location l = new Location(loc.x + x, loc.y + y, loc.z);

                    if (MountainVoxel.get(l) != null)
                    {
                        continue;                               // if it's mountain, OK.
                    }
                    // otherwise, make sure that nothing is on it.
                    if (World.world[l.x, l.y, l.z + 1] != null)
                    {
                        return(false);
                    }
                    // and nothing is under it
                    if (World.world[l.x, l.y, l.z] != null)
                    {
                        return(false);
                    }
                }
            }

            if (World.world.isOutsideWorld(loc))
            {
                return(false);
            }

            return(true);
        }