コード例 #1
0
        public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move)
        {
            if (tilePath.Count < 2)
                return false;

            var current = MyStrategy.map.tileAt(vehicle.position);

            var currentToFirst = current.directionForTile(tilePath[0]).Value;
            var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value;
            var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value;

            if (currentToFirst.isSameAxis(firstToSecond))
                return false;

            if (currentToFirst.back() != secondToThird)
                return false;

            var turningFrom = new Vector(currentToFirst);
            var turningTo = new Vector(firstToSecond);

            if (vehicle.speed.length > 10) {

                var steering = Math.Sign(turningFrom.angleTo(turningTo));

                var backWall = new Ray(
                    tilePath[0].center + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * Constants.tileSize * 0.5,
                    turningTo * Constants.tileSize * 2
                );

                var backSideWall = new Ray(
                    backWall.p2 - turningTo * Constants.roadMargin,
                    -turningFrom * (Constants.tileSize - Constants.roadMargin)
                );

                var innerWall = new Ray(current.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5,
                                    turningFrom * Constants.tileSize);

                var innerCircle = new Circle(current.center + (new Vector(currentToFirst) + new Vector(firstToSecond)) * Constants.tileSize * 0.5, Constants.roadMargin);

                backWall.draw(0x00FF00);
                backSideWall.draw(0x00FF00);
                innerWall.draw(0x00FF00);
                innerCircle.draw(0x00FF00);

                var vv = new VirtualVehicle(vehicle);

                for (int i = 0; i < 100; ++i) {

                    vv.simulateTick(0.5, steering);

                    var rect = vv.rect;

                    if (rect.isIntersect(innerWall) || rect.isIntersect(innerCircle)) {
                        move.EnginePower = 1;
                        move.WheelTurn = -steering;
                        move.IsBrake = false;
                        return true;
                    }

                    if (rect.isIntersect(backWall) || rect.isIntersect(backSideWall)) {
                        move.IsBrake = false;
                        move.EnginePower = -1;
                        //move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, current.center, turningTo, -0.25 * Constants.tileSize));
                        move.WheelTurn = steering;
                        return true;
                    }

                    vv.position.draw(0xFF0000);
                    vv.rect.draw(0x0000FF);

                }
            }

            move.EnginePower = 0.5;
            move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, current.center, turningTo, -0.25 * Constants.tileSize));
            move.IsBrake = false;
            return true;
        }
コード例 #2
0
        public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move)
        {
            if (tilePath.Count < 3)
                return false;

            var currentTile = MyStrategy.map.tileAt(vehicle.position);

            Vector turningTo;
            Vector turningFrom;

            {

                var currentToFirst = currentTile.directionForTile(tilePath[0]).Value;
                var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value;
                var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value;

                if (currentToFirst != firstToSecond)
                    return false;

                if (firstToSecond.isSameAxis(secondToThird))
                    return false;

                if (tilePath.Count >= 4) {
                    if (tilePath[2].directionForTile(tilePath[3]).Value.back() == currentToFirst)
                        return false;
                }

                turningFrom = new Vector(currentToFirst);
                turningTo = new Vector(secondToThird);
            }

            if (vehicle.speed.length > 10 && vehicle.forward * turningFrom > 0.45) {
                var vv = new VirtualVehicle(vehicle);
                var steering = Math.Sign(turningFrom.angleTo(turningTo));

                var innerSide1 = Ray.line(
                    currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5,
                    currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) + turningFrom * Constants.tileSize * 0.5
                );

                //innerSide1.draw(0x00FF00);

                var innerSide2 = new Ray(innerSide1.position + turningFrom * Constants.tileSize, innerSide1.direction);

                //innerSide2.draw(0x00FF00);

                var innerCircle = new Circle(currentTile.center + (turningTo + turningFrom) * Constants.tileSize * 0.5 + turningFrom * Constants.tileSize, Constants.roadMargin);

                //innerCircle.draw(0x00FF00);

                var backWall = new Ray(tilePath[1].center + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * (Constants.tileSize * 0.5), turningTo * 2 * Constants.tileSize);

                //backWall.draw(0x00FF00);

                var outerSide = new Ray(currentTile.center - turningTo * (Constants.halfTileSize - Constants.roadMargin) - turningFrom * Constants.halfTileSize, turningFrom * Constants.tileSize * 3);

                //outerSide.draw(0x00FF00);

                for (int i = 0; i < 100; ++i) {
                    vv.simulateTick(1.0, steering);
                    if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerSide2))
                        break;

                    if (vv.rect.isIntersect(innerCircle))
                        break;

                    if (vv.rect.isIntersect(outerSide)) {
                        var target = currentTile.center + turningFrom * Constants.tileSize * 1.5;

                        move.WheelTurn = steering;
                        move.EnginePower = 1;
                        move.IsBrake = true;

                        return true;
                    }

                    if (vv.rect.isIntersect(backWall)) {
                        move.EnginePower = 1;
                        move.WheelTurn = steering;
                        move.IsBrake = true;
                        return true;
                    }

                    if (tilePath[2].rect.contains(vv.position)) {

                        // защита от слишком быстрого захода в поворот и ударения в заднюю стенку

                        for (int j = 0; j < 50; ++j) {

                            vv.simulateTick(1, steering);
                            if (vv.rect.isIntersect(backWall)) {
                                move.EnginePower = 1;
                                move.WheelTurn = steering;
                                move.IsBrake = true;
                                return true;
                            }

                            //vv.position.draw(0x00FF00);
                            //vv.rect.draw(0x0000FF);

                        }

                        move.EnginePower = 1;
                        move.WheelTurn = steering;
                        move.IsBrake = false;
                        return true;

                    }

                    //vv.position.draw(0xFF0000);
                    //vv.rect.draw(0x0000FF);
                }

            }

            move.WheelTurn = vehicle.steeringAngleForDirection((currentTile.center + turningFrom * Constants.tileSize * 1.5) - vehicle.position);
            move.EnginePower = 1;
            move.IsBrake = false;

            return true;
        }
コード例 #3
0
        public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move)
        {
            if (tilePath.Count < 3)
                return false;

            var currentTile = MyStrategy.map.tileAt(vehicle.position);

            Vector turningTo;
            Vector turningFrom;

            {
                var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value;

                turningTo = new Vector(firstToSecond);

                if (firstToSecond != tilePath[1].directionForTile(tilePath[2])) {
                    return false;
                }

                var currentToFirst = currentTile.directionForTile(tilePath[0]).Value;
                if (currentToFirst.isSameAxis(firstToSecond)) {
                    return false;
                }

                turningFrom = new Vector(currentToFirst);

            }

            if (vehicle.speed.length > 10) {

                var innerSide1 = Ray.line(
                    currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5,
                    currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) + turningFrom * Constants.tileSize * 0.5
                );

                //innerSide1.draw(0x00FF00);

                var innerCircle = new Circle(currentTile.center + (turningTo + turningFrom) * Constants.tileSize * 0.5, Constants.roadMargin);

                //innerCircle.draw(0x00FF00);

                var innerCircleExtended = new Circle(innerCircle.position, innerCircle.radius + 10);

                var backWall = new Ray(tilePath[0].center  + turningFrom * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningTo * Constants.tileSize * 0.5,
                                   turningTo * Constants.tileSize * 2);

                //backWall.draw(0x00FF00);

                if (vehicle.forward * turningFrom > 0.45) {
                    var vv = new VirtualVehicle(vehicle);
                    var steering = Math.Sign(turningFrom.angleTo(turningTo));

                    for (int i = 0; i < 100; ++i) {
                        vv.simulateTick(1.0, steering);

                        if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerCircle)) {
                            move.EnginePower = 1;
                            move.WheelTurn = vehicle.steeringAngleForDirection(vehicle.stabilizationDir(turningFrom, currentTile.center, turningTo, -0.15 * Constants.tileSize));
                            move.IsBrake = false;
                            return true;
                        }

                        if (vv.rect.isIntersect(backWall)) {
                            move.IsBrake = true;
                            move.EnginePower = 1;
                            move.WheelTurn = steering;
                            return true;
                        }

                        if (tilePath[1].rect.contains(vv.position)) {

                            // защита от слишком быстрого захода в поворот и ударения в заднюю стенку

                            for (int j = 0; j < 50; ++j) {

                                vv.simulateTick(1, steering);
                                if (vv.rect.isIntersect(backWall)) {
                                    move.EnginePower = 1;
                                    move.WheelTurn = steering;
                                    move.IsBrake = true;
                                    return true;
                                }

                                //vv.position.draw(0x00FF00);
                                //vv.rect.draw(0x0000FF);

                            }

                            move.EnginePower = 1;
                            move.WheelTurn = steering;
                            move.IsBrake = false;
                            return true;
                        }

                        //vv.position.draw(0xFF0000);
                        //vv.rect.draw(0x0000FF);
                    }
                } else if (vehicle.forward * turningTo > 0.5) {

                    var vv = new VirtualVehicle(vehicle);
                    var steering = Math.Sign(turningFrom.angleTo(turningTo));

                    for (int i = 0; i < 100; ++i) {
                        vv.simulateTick(1.0, 0);

                        if (vv.rect.isIntersect(innerSide1) || vv.rect.isIntersect(innerCircleExtended)) {

                            move.EnginePower = 1;
                            move.WheelTurn = -steering;
                            move.IsBrake = false;
                            return true;
                        }

                        if (tilePath[1].rect.contains(vv.position)) {
                            move.EnginePower = 1;
                            move.WheelTurn = 0;
                            move.IsBrake = false;
                            return true;
                        }

                        //vv.position.draw(0xFF0000);
                        //vv.rect.draw(0x0000FF);
                    }
                } else {
                    move.IsBrake = true;
                    move.WheelTurn = 0;
                    move.EnginePower = 1;
                    return true;
                }

            }

            move.IsBrake = false;
            move.EnginePower = 1;
            var turn = turningTo + turningFrom;
            move.WheelTurn = vehicle.steeringAngleForDirection(turn);

            return true;
        }
コード例 #4
0
        public override bool tryDrive(Vehicle vehicle, List<Tile> tilePath, Move move)
        {
            if (tilePath.Count < 3)
                return false;

            var currentTile = MyStrategy.map.tileAt(vehicle.position);
            Vector target;
            Vector turningFrom;
            Vector turningTo;

            {

                var currentToFirst = currentTile.directionForTile(tilePath[0]).Value;
                var firstToSecond = tilePath[0].directionForTile(tilePath[1]).Value;
                var secondToThird = tilePath[1].directionForTile(tilePath[2]).Value;

                if (currentToFirst != secondToThird) {
                    return false;
                }

                if (firstToSecond.isSameAxis(currentToFirst)) {
                    return false;
                }

                turningFrom = new Vector(currentToFirst);
                turningTo = new Vector(firstToSecond);

                target = tilePath[2].center - turningFrom * 0.5 * Constants.tileSize;

            }

            var vehicleToTarget = target - vehicle.position;

            if (vehicle.speed.length > 10 && vehicle.forward * (turningFrom + turningTo) > 0) {

                var steering = Math.Sign(turningFrom.angleTo(turningTo));

                Ray side = new Ray(
                               tilePath[0].center - turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5,
                               turningFrom * (Constants.tileSize - Constants.roadMargin)
                           );

                Ray back = new Ray(side.p2, turningTo * (Constants.tileSize - Constants.roadMargin));

                Circle backCircle = new Circle(back.p2 + turningFrom * Constants.roadMargin, Constants.roadMargin);

                Ray innerSide = new Ray(
                    currentTile.center + turningTo * (Constants.tileSize * 0.5 - Constants.roadMargin) - turningFrom * Constants.tileSize * 0.5,
                    turningFrom * Constants.tileSize
                );

                Circle innerCircle = new Circle(innerSide.p2 + turningTo * Constants.roadMargin, Constants.roadMargin);

                side.draw(0x00FF00);
                back.draw(0x00FF00);
                backCircle.draw(0x00FF00);

                innerSide.draw(0x00FF00);
                innerCircle.draw(0x00FF00);

                var vv = new VirtualVehicle(vehicle);

                for (int i = 0; i < 100; ++i) {
                    vv.simulateTick(1.0, 0.0);

                    var rect = vv.rect;

                    if (rect.isIntersect(side) || rect.isIntersect(back) || rect.isIntersect(backCircle)) {

                        vv = new VirtualVehicle(vehicle);

                        for (int j = 0; j < 100; ++j) {
                            vv.simulateTick(1, steering);

                            if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) {
                                move.EnginePower = 1;
                                move.IsBrake = true;
                                move.WheelTurn = steering;
                                return true;
                            }
                        }

                        move.EnginePower = 1;
                        move.IsBrake = false;
                        move.WheelTurn = steering;
                        return true;
                    } else if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) {

                        vv = new VirtualVehicle(vehicle);

                        for (int j = 0; j < 100; ++j) {
                            vv.simulateTick(1, -steering);

                            if (rect.isIntersect(innerSide) || rect.isIntersect(innerCircle)) {
                                move.EnginePower = 1;
                                move.IsBrake = true;
                                move.WheelTurn = -steering;
                                return true;
                            }
                        }

                        move.EnginePower = 1;
                        move.IsBrake = false;
                        move.WheelTurn = -steering;
                        return true;
                    }

                    if (tilePath[2].rect.contains(vv.position)) {
                        move.EnginePower = 1;
                        move.IsBrake = false;
                        move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget);
                        return true;
                    }

                    rect.draw(0x0000FF);
                    vv.position.draw(0xFF0000);
                }

                move.EnginePower = 1;
                move.IsBrake = false;
                move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget);

                //new Ray(vehicle.position, vehicleToTarget).draw(0x00FFFF);

                return true;

            }

            if (vehicle.forward * vehicleToTarget < 0.5) {
                if (vehicle.speed.length > 10) {
                    move.IsBrake = true;
                }
                move.EnginePower = 0.3;
            } else {
                move.EnginePower = 1;
            }
            move.WheelTurn = vehicle.steeringAngleForDirection(vehicleToTarget);
            move.IsBrake = false;

            return true;
        }
コード例 #5
0
ファイル: Tile.cs プロジェクト: WideWord/strategy2015
        public LinkedList<Vector> multiIntersect(Ray ray)
        {
            var intersections = new LinkedList<Vector>();

            var rays = new LinkedList<Ray>();
            var arcs = new LinkedList<Arc>();

            getEdges(rays, arcs);

            foreach (var side in rays) {

                var sideIntersection = ray.intersect(side);

                if (sideIntersection != null) {
                    intersections.AddLast(sideIntersection ?? new Vector());
                }
            }

            foreach (var arc in arcs) {

                var arcIntersections = arc.multiIntersect(ray);

                if (arcIntersections != null) {
                    foreach (var inters in arcIntersections) {
                        intersections.AddLast(inters);
                    }
                }

            }

            return intersections;
        }
コード例 #6
0
ファイル: Tile.cs プロジェクト: WideWord/strategy2015
        void getEdges(LinkedList<Ray> rays, LinkedList<Arc> arcs)
        {
            foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) {
                if (!canGoInDirection(dir)) {

                    var sideCenter = center + new Vector(dir) * (Constants.tileSize * 0.5 - Constants.roadMargin);
                    var sideHalfLength = (Constants.tileSize * 0.5 - Constants.roadMargin * 2);
                    var side = Ray.line(
                        sideCenter + new Vector(dir.turnLeft()) * sideHalfLength,
                        sideCenter + new Vector(dir.turnRight()) * sideHalfLength
                    );

                    rays.AddLast(side);
                }

                var nextDir = dir.turnLeft();

                if (!canGoInDirection(dir) && !canGoInDirection(nextDir)) {
                    var arcCenter = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5 - Constants.roadMargin * 2);

                    var arc = new Arc(arcCenter, Constants.roadMargin, nextDir.angle(), dir.angle());

                    arcs.AddLast(arc);

                } else if (canGoInDirection(dir) && canGoInDirection(nextDir)) {

                    var arcCenter = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5);

                    var arc = new Arc(arcCenter, Constants.roadMargin, nextDir.back().angle(), dir.back().angle());

                    arcs.AddLast(arc);

                } else if (!canGoInDirection(dir) && canGoInDirection(nextDir)) {

                    var lineFrom = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5);
                    lineFrom = lineFrom - (new Vector(dir) * Constants.roadMargin);

                    var side = new Ray(lineFrom, new Vector(nextDir.back()) * Constants.roadMargin * 2);

                    rays.AddLast(side);

                } else if (canGoInDirection(dir) && !canGoInDirection(nextDir)) {

                    var lineFrom = center + (new Vector(dir) + new Vector(nextDir)) * (Constants.tileSize * 0.5);
                    lineFrom = lineFrom - (new Vector(nextDir) * Constants.roadMargin);

                    var side = new Ray(lineFrom, new Vector(dir.back()) * Constants.roadMargin * 2);

                    rays.AddLast(side);
                }
            }
        }
コード例 #7
0
ファイル: Tile.cs プロジェクト: WideWord/strategy2015
        public Vector? intersect(Ray ray)
        {
            var intersections = multiIntersect(ray);

            if (intersections.Count == 0)
                return null;

            Vector? vec = null;
            var dist = double.MaxValue;

            foreach (var intersection in intersections) {
                var curDist = (intersection - ray.position).length;
                if (curDist < dist) {
                    dist = curDist;
                    vec = intersection;
                }
            }

            return vec;
        }
コード例 #8
0
ファイル: Tile.cs プロジェクト: WideWord/strategy2015
        public bool isIntersect(Ray ray)
        {
            var rays = new LinkedList<Ray>();
            var arcs = new LinkedList<Arc>();

            getEdges(rays, arcs);

            foreach (var side in rays) {

                var sideIntersection = ray.intersect(side);

                if (sideIntersection != null) {
                    return true;
                }
            }

            foreach (var arc in arcs) {

                var arcIntersections = arc.multiIntersect(ray);

                if (arcIntersections != null) {
                    return true;
                }

            }

            return false;
        }
コード例 #9
0
ファイル: Vector.cs プロジェクト: WideWord/strategy2015
        public AxisDirection? borderAnyIntersectionDirection(Ray ray, AxisDirection? exceptDir = null)
        {
            foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) {
                if (dir == exceptDir)
                    continue;

                var side = lineForDirection(dir);
                if (ray.intersect(side) != null) {
                    //(ray.intersect(side) ?? new Vector(0, 0)).draw(0xFF0000);
                    return dir;
                }

            }
            return null;
        }
コード例 #10
0
ファイル: Vector.cs プロジェクト: WideWord/strategy2015
        public Vector? intersect(Ray o)
        {
            var p = position;
            var r = direction;

            var q = o.position;
            var s = o.direction;

            if (r.cross (s) == 0) {
                return null;
            } else {
                var t = (q - p).cross(s) / r.cross(s);
                var u = -(p - q).cross(r) / r.cross(s);

                if (t >= 0 && t <= 1 && u >= 0 && u <= 1) {
                    return p + t * r;
                } else {
                    return null;
                }
            }
        }
コード例 #11
0
ファイル: Vector.cs プロジェクト: WideWord/strategy2015
        public bool isIntersect(Ray ray)
        {
            foreach (AxisDirection dir in Enum.GetValues(typeof(AxisDirection))) {
                var edge = edgeInDirection(dir);
                if (ray.intersect(edge) != null) {
                    return true;
                }
            }

            return false;
        }
コード例 #12
0
ファイル: Vector.cs プロジェクト: WideWord/strategy2015
        public bool isIntersect(Ray ray)
        {
            var e = ray.position;
            var d = ray.direction;
            var f = e - position;

            var a = d * d;
            var b = 2 * (f * d);
            var c = (f * f) - radius * radius;

            var D = b * b - 4 * a * c;

            if (D < 0)
                return false;

            if (D == 0) { // impossible
                D = 0.00001;
            }

            var sD = Math.Sqrt(D);
            var a2 = a * 2;

            var t1 = (-b + sD) / a2;
            var t2 = (-b - sD) / a2;

            var p1 = ray.position + ray.direction * t1;
            var p2 = ray.position + ray.direction * t2;

            var havePoint1 = t1 >= 0 && t1 <= 1;
            var havePoint2 = t2 >= 0 && t2 <= 1;

            return havePoint1 || havePoint2;
        }
コード例 #13
0
ファイル: Vector.cs プロジェクト: WideWord/strategy2015
        public Vector[] multiIntersect(Ray ray)
        {
            var e = ray.position;
            var d = ray.direction;
            var f = e - position;

            var a = d * d;
            var b = 2 * (f * d);
            var c = (f * f) - radius * radius;

            var D = b * b - 4 * a * c;

            if (D < 0)
                return null;

            if (D == 0) { // impossible
                D = 0.00001;
            }

            var sD = Math.Sqrt(D);
            var a2 = a * 2;

            var t1 = (-b + sD) / a2;
            var t2 = (-b - sD) / a2;

            var p1 = ray.position + ray.direction * t1;
            var p2 = ray.position + ray.direction * t2;

            var havePoint1 = t1 >= 0 && t1 <= 1 && isPointInArcSector(p1);
            var havePoint2 = t2 >= 0 && t2 <= 1 && isPointInArcSector(p2);

            if (havePoint1 && havePoint2) {
                return new Vector[] { p1, p2 };
            } else if (havePoint1) {
                return new Vector[] { p1 };
            } else if (havePoint2) {
                return new Vector[] { p2 };
            } else {
                return null;
            }
        }