Skip to content

using System; using System.Linq; using AIRLab.Mathematics; using ClientBase; using CommonTypes; using CVARC.Basic.Controllers; using CVARC.Network; using RepairTheStarship.Sensors; using MapHelper; using System.Collections.Generic; using CVARC.Basic; namespace Example { internal class Program { private static readonly ClientSettings Settings = n…

Notifications You must be signed in to change notification settings

Ngbtl95/Program.cs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 

Repository files navigation

using System; using System.Linq; using AIRLab.Mathematics; using ClientBase; using CommonTypes; using CVARC.Basic.Controllers; using CVARC.Network; using RepairTheStarship.Sensors; using MapHelper; using System.Collections.Generic; using CVARC.Basic;

namespace Example { internal class Program { private static readonly ClientSettings Settings = new ClientSettings { Side = Side.Left, //Переключив это поле, можно отладить алгоритм для левой или правой стороны, а также для произвольной стороны, назначенной сервером LevelName = LevelName.Level2, //Задается уровень, в котором вы хотите принять участие MapNumber = -1 //Задавая различные значения этого поля, вы можете сгенерировать различные случайные карты };

    private static void Main(string[] args)
    {
        var server = new CvarcClient(args, Settings).GetServer<PositionSensorsData>();
        var helloPackageAns = server.Run();
        var side = helloPackageAns.RealSide;
        var sensorsData = helloPackageAns.SensorsData;
        string lastColorDetail = "";

        while (sensorsData.MapSensor.MapItems.GetDatails().FirstOrDefault() != null)
        {
            if (!sensorsData.DetailsInfo.HasGrippedDetail)
            {
                var x = sensorsData.Position.PositionsData[sensorsData.RobotId.Id].X;
                var y = sensorsData.Position.PositionsData[sensorsData.RobotId.Id].Y;
                var min = sensorsData.MapSensor.
                                        MapItems.
                                        GetDatails().
                                        Min(item => new Tuple<double, string>(item.Item1.Distance(x, y), item.Item2));
                if (min.Item1 < 25)
                {
                    lastColorDetail = min.Item2;
                    sensorsData = server.SendCommand(new Command { Action = CommandAction.Grip, Time = 1 });
                }
                if (!sensorsData.DetailsInfo.HasGrippedDetail)
                    sensorsData = server.SendCommand(GetStepToDetail(sensorsData));
            }
            else
            {
                var x = sensorsData.Position.PositionsData[sensorsData.RobotId.Id].X;
                var y = sensorsData.Position.PositionsData[sensorsData.RobotId.Id].Y;
                var min = sensorsData.MapSensor.
                                        MapItems.
                                        GetSockets(lastColorDetail).
                                        Select(item => item.Item1).
                                        Min(item => item.Distance(x, y));
                if (min < 35)
                {
                    sensorsData = server.SendCommand(new Command { Action = CommandAction.Release, Time = 1 });
                }
                if (sensorsData.DetailsInfo.HasGrippedDetail)
                    sensorsData = server.SendCommand(GetStepToWall(sensorsData, lastColorDetail));
            }
        }

        server.Exit();
    }

    private static Command GetStepToWall(PositionSensorsData data, string color)
    {
        var disabledEgde = GetDisabledEdge(data.MapSensor.MapItems, 4, 6);
        var map = new int[4, 6];
        var robot = data.Position.PositionsData[data.RobotId.Id];
        var robot2 = data.Position.PositionsData[(data.RobotId.Id + 1) % 2];
        var start = Normalize(robot.X, robot.Y); 
        map[start.Y, start.X] = 1;
        map[NormalizeY(robot2.Y), NormalizeX(robot2.X)] = -1;
        var queue = new Queue<Point>();
        queue.Enqueue(start);
        while (queue.Count!=0)
        {
            var cur = queue.Dequeue();
            foreach (var p in GetNeighbouringCells(cur))
                if (p.X >= 0 && p.Y >= 0 && p.X < map.GetLength(1) && p.Y < map.GetLength(0) && map[p.Y, p.X] == 0 && (!disabledEgde[cur.Y, cur.X, p.Y, p.X]))
                {
                    map[p.Y, p.X] = map[cur.Y, cur.X] + 1;
                    queue.Enqueue(p);
                }
        }
        var f = data.MapSensor.
                            MapItems.
                            GetSockets(color).
                            SelectMany(item => GetNeighbouringCells(item.Item1, item.Item2)).
                            Min(item =>
                            {
                                if (map[item.Y, item.X] != 0 && map[item.Y, item.X] != -1)
                                    return new Tuple<int, Point>(map[item.Y, item.X], item);
                                else
                                    return new Tuple<int, Point>(int.MaxValue, item);
                            }).
                            Item2;
        Point next;
        if (f.X == start.X && f.Y == start.Y)
        {
            var x = data.Position.PositionsData[data.RobotId.Id].X;
            var y = data.Position.PositionsData[data.RobotId.Id].Y;
            var finish = data.MapSensor.
                                MapItems.
                                GetSockets(color).
                                Min(item => new Tuple<double, Point2D>(Normalize(item.Item1).Distance(new Point((int)x, (int)y)), item.Item1)).
                                Item2;
            next = new Point((int)finish.X, (int)finish.Y);
        }
        else
        {
            var n = f;
            while (f.X != start.X || f.Y != start.Y)
            {
                n = f;
                foreach (var p in GetNeighbouringCells(f))
                    if (p.X >= 0 && p.Y >= 0 && p.X < map.GetLength(1) && p.Y <= map.GetLength(0) && (map[p.Y, p.X] == map[f.Y, f.X] - 1) && (!disabledEgde[f.Y, f.X, p.Y, p.X]))
                    {
                        f = p;
                        break;
                    }
            }
            next = new Point(n.X * 50 + 25 - 150, 100 - (n.Y * 50 + 25));
        }

        return MotionDetection(robot, next);
    } 
    
    public static Command MotionDetection(CVARC.Basic.Sensors.PositionData robot, Point next)
    {
        var e = Angle.FromRad(Math.Atan2(next.Y - robot.Y, next.X - robot.X)).Grad;
        if (((int)e + 360) % 360 == ((int)robot.Angle + 360) % 360)
            return new Command { LinearVelocity = 50, Time = Math.Abs(next.Distance(new Point((int)robot.X, (int)robot.Y)) - 10) / 50.0 };
        else
            if ((Math.Abs((int)e - (int)robot.Angle) < 180))
                return new Command { AngularVelocity = Angle.FromGrad(Math.Sign(e - robot.Angle) * 90), Time = Math.Abs(e - robot.Angle) / 90.0 };
            else
                if (Math.Abs((int)e - (int)robot.Angle) < 200)
                    return new Command { LinearVelocity = -50, Time = Math.Abs(next.Distance(new Point((int)robot.X, (int)robot.Y))) / 50.0 };
                else
                    return new Command { AngularVelocity = Angle.FromGrad(Math.Sign(robot.Angle - e) * 90), Time = Math.Abs(360 + robot.Angle - e) / 90.0 };
    }

    public static Command GetStepToDetail(PositionSensorsData data)
    {
        var disabledEgde = GetDisabledEdge(data.MapSensor.MapItems, 4, 6);
        var map = new int[4, 6];
        var robot = data.Position.PositionsData[data.RobotId.Id];
        var robot2 = data.Position.PositionsData[(data.RobotId.Id + 1) % 2];
        var start = Normalize(robot.X, robot.Y);
        map[start.Y, start.X] = 1;
        map[NormalizeY(robot2.Y), NormalizeX(robot2.X)] = -1;
        var queue = new Queue<Point>();
        queue.Enqueue(start);
        while (queue.Count != 0)
        {
            var cur = queue.Dequeue();
            foreach (var p in GetNeighbouringCells(cur))
                if (p.X >= 0 && p.Y >= 0 && p.X < map.GetLength(1) && p.Y < map.GetLength(0) && map[p.Y, p.X] == 0 && (!disabledEgde[cur.Y, cur.X, p.Y, p.X]))
                {
                    map[p.Y, p.X] = map[cur.Y, cur.X] + 1;
                    queue.Enqueue(p);
                }
        }
        var f = data.MapSensor.
                    MapItems.
                    GetDatails().
                    Select(item => Normalize(item.Item1)).
                    Min(item =>
                    {
                        if (map[item.Y, item.X] != 0 && map[item.Y, item.X] != -1)
                            return new Tuple<int, Point>(map[item.Y, item.X], item);
                        else
                            return new Tuple<int, Point>(int.MaxValue, item);
                    }).
                    Item2;
        if (map[f.Y, f.X] == 0)
            throw new Exception();
        Point next;
        if (f.X == start.X && f.Y == start.Y)
        {
            var x = data.Position.PositionsData[data.RobotId.Id].X;
            var y = data.Position.PositionsData[data.RobotId.Id].Y;
            var finish = data.MapSensor.
                                MapItems.
                                GetDatails().
                                Min(item => new Tuple<double, Point2D>(Normalize(item.Item1).Distance(new Point((int)x, (int)y)), item.Item1)).
                                Item2;
            next = new Point((int)finish.X, (int)finish.Y);
        }
        else
        {
            var n = f;
            while (f.X != start.X || f.Y != start.Y)
            {
                n = f;
                foreach (var p in GetNeighbouringCells(f))
                    if (p.X >= 0 && p.Y >= 0 && p.X < map.GetLength(1) && p.Y <= map.GetLength(0) && (map[p.Y, p.X] == map[f.Y, f.X] - 1) && (!disabledEgde[f.Y, f.X, p.Y, p.X]))
                    {
                        f = p;
                        break;
                    }
            }
            next = new Point(n.X * 50 + 25 - 150, 100 - (n.Y * 50 + 25));
        }
        return MotionDetection(robot, next);
    }

    static IEnumerable<Point> GetNeighbouringCells(Point2D point, bool type)
    {
        var p = Normalize(point);
        if (type)
        {
            if (p.X - 1 >= 0)
                yield return new Point(p.X - 1, p.Y);
        }
        else if (p.Y - 1 >= 0)
            yield return new Point(p.X, p.Y - 1);
        yield return new Point(p.X, p.Y);
    }

    static IEnumerable<Point> GetNeighbouringCells(Point point)
    {
        return
            from x in new[] { -1, 0, 1 }
            from y in new[] { -1, 0, 1 }
            where Math.Abs(x) + Math.Abs(y) == 1
            let p = new Point(point.X + x, point.Y + y)
            select p;
    }

    static bool[, , ,] GetDisabledEdge(MapItem[] items, int w, int h)
    {
        var ans = new bool[w, h, w, h];
        foreach (var point in items.GetVerticalWalls())
        {
            var p = Normalize(point);
            ans[p.Y, p.X, p.Y, p.X - 1] = true;
            ans[p.Y, p.X - 1, p.Y, p.X] = true;
        }
        foreach (var point in items.GetVerticalSockets())
        {
            var p = Normalize(point);
            ans[p.Y, p.X, p.Y, p.X - 1] = true;
            ans[p.Y, p.X - 1, p.Y, p.X] = true;
        }
        foreach (var point in items.GetHorizontalWalls())
        {
            var p = Normalize(point);
            ans[p.Y, p.X, p.Y - 1, p.X] = true;
            ans[p.Y - 1, p.X, p.Y, p.X] = true;
        }
        foreach (var point in items.GetHorizontalSockets())
        {
            var p = Normalize(point);
            ans[p.Y, p.X, p.Y - 1, p.X] = true;
            ans[p.Y - 1, p.X, p.Y, p.X] = true;
        }
        return ans;
    }

    static Point Normalize(Point2D point)
    {
        return new Point(NormalizeX(point.X), NormalizeY(point.Y));
    }

    static Point Normalize(double x, double y)
    {
        return new Point(NormalizeX(x), NormalizeY(y));
    }

    static int NormalizeX(double x)
    {
        return ((int)x + 150) / 50;
    }

    static int NormalizeY(double y)
    {
        return (100 - (int)y) / 50;
    }
}

public static class ForPoint2D
{
    public static double Distance(this Point2D a, double x, double y)
    {
        return Math.Sqrt((a.X - x) * (a.X - x) + (a.Y - y) * (a.Y - y));
    }
}

public static class ForPoint
{
    public static double Distance(this Point a, Point b)
    {
        return Math.Sqrt((a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y));
    }
}

public static class ForMapItems
{
    public static IEnumerable<Tuple<Point2D, string>> GetDatails(this MapItem[] items)
    {
        return items.Where(item => item.Tag.EndsWith("Detail")).Select(item => new Tuple<Point2D, string>(new Point2D(item.X, item.Y), item.Tag.Substring(0, item.Tag.Length - 6)));
    }

    public static IEnumerable<Point2D> GetVerticalSockets(this MapItem[] items)
    {
        return items.Where(item => item.Tag.EndsWith("Socket")).Where(item => item.Tag.StartsWith("Vertical")).Select(item => new Point2D(item.X, item.Y));
    }

    public static IEnumerable<Point2D> GetHorizontalSockets(this MapItem[] items)
    {
        return items.Where(item => item.Tag.EndsWith("Socket")).Where(item => item.Tag.StartsWith("Horizontal")).Select(item => new Point2D(item.X, item.Y));
    }

    public static IEnumerable<Tuple<Point2D, bool>> GetSockets(this MapItem[] items, string color)
    {
        return items.Where(item => item.Tag.EndsWith(color + "Socket")).Select(item => new Tuple<Point2D, bool>(new Point2D(item.X, item.Y), item.Tag.IndexOf("Vertical") != -1));
    }

    public static IEnumerable<Point2D> GetVerticalWalls(this MapItem[] items)
    {
        return items.Where(item => item.Tag.EndsWith("Wall")).Where(item => item.Tag.StartsWith("Vertical")).Select(item => new Point2D(item.X, item.Y));
    }

    public static IEnumerable<Point2D> GetHorizontalWalls(this MapItem[] items)
    {
        return items.Where(item => item.Tag.EndsWith("Wall")).Where(item => item.Tag.StartsWith("Horizontal")).Select(item => new Point2D(item.X, item.Y));
    }
}

}

About

using System; using System.Linq; using AIRLab.Mathematics; using ClientBase; using CommonTypes; using CVARC.Basic.Controllers; using CVARC.Network; using RepairTheStarship.Sensors; using MapHelper; using System.Collections.Generic; using CVARC.Basic; namespace Example { internal class Program { private static readonly ClientSettings Settings = n…

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published