Sun
SDK: 1.44


Сегодня в Галактике
Всего конкурсантов: 1018
Кораблей создано: 20
Лидер рейтинга: dabino
Лучший сегодня: dabino


Царь Горы  »

Планы на будущее  »

SDK 1.43  »

Правила проведения финала  »

Обновление SDK для финала  »

III Этап: победители студенческого зачета  »

Завершен III этап конкурса. Победитель - ant  »

Пригласи друзей на конкурс  »

Дополнительные призы для студентов!  »

 Победитель I этапа

Победитель: Роман Антипин (ant)

Мне 26 лет, живу в Санкт-Петербурге. В 2005 году закончил СПбГТИ(ТУ) кафедру "Систем автоматизированного проектирования и управления". В 2008 защитил кандидатскую диссертацию по специальности "Системный анализ, управление и обработка информации". Работаю ведущим Java-программистом в ООО "Абисофт", по совместительству - старшим преподавателем в СПбГТИ(ТУ). Увлекаюсь большим теннисом и роликами.

  • Откуда Вы узнали о конкурсе GalaxyFX?
    О конкурсе узнал, посетив конференцию Sun Tech Days 2009

  • Что Вас больше всего привлекло в конкурсе?
    Сама идея состязания представляется интересной, а также красочное оформление игрового мира, что, безусловно, является сильной стороной JavaFX.

  • Насколько трудно/легко досталась вам победа?
    Это только первый этап, думаю, вся борьба еще впереди.

  • Много ли времени отняло у Вас участие в конкурсе?
    Обычно 1-2 часа после работы, но бывало и больше.

  • Давно ли Вы программируете на JavaFX? А на Java?
    На JavaFX программирую с начала конкурса, на Java - 5 лет.

  • Вы выиграли этап. Планируете ли Вы участвовать дальше?
    Да, безусловно, игра достаточно увлекательная и затягивает.

  • Вы бы посоветовали своим друзьям и коллегам принять участие в конкурсе Galaxy FX?
    Да, я рассказывал коллегам про конкурс.

  • Не хотите посоветовать что-нибудь разработчикам? Какие улучшения стоит внести?
    На мой взгляд, стоит опубликовывать карты прошедших состязаний, для того чтобы участники имели возможность тестировать свои алгоритмы. В целом, разработчики довольно оперативно вносят изменения, особенно, учитывая, что для них это не основная задача.

Итоговый рейтинг I этапа

 

Результаты состязаний по дням

 Корабль победителя

package galaxyfx;

/**
 * @author rantipin
 */

import galaxyfx.program.*;
import galaxyfx.program.action.*;
import galaxyfx.spacecraft.system.Point;
import galaxyfx.spacecraft.system.ResourceItem;
import galaxyfx.spacecraft.system.SpaceCraftItem;
import java.lang.Math;
import java.util.Comparator;
import javafx.util.Sequences;


class ResourceItemWithTime {
    var time: Number;
    var resourceItem: ResourceItem;
}

class OptimTimeForWinResourceCount {
    var timeoutExit: Boolean;
    var time: Number;
    var resourceSum: Number;
    var resources: ResourceItem[];
    var stopResource: ResourceItem;
}

class NearestDistForMeAndStranger {
    var forMe: ResourceItem[];
    var forStranger: ResourceItem[];
}

function sign(x:Number):Integer{
    if ( x < 0 ) -1 else if ( 0 < x ) 1 else 0;
}

class ComparatorForMinDistanceFirst extends Comparator {
    var spaceCraft : SpaceCraftItem;
    var prg: Program;

    public override function compare(obj1:Object, obj2: Object):Integer{
        return sign (prg.distanceTime(spaceCraft, [(obj1 as ResourceItem)]) -
               prg.distanceTime(spaceCraft, [(obj2 as ResourceItem)]));
    }

    public override function equals(obj:Object) : Boolean {
        if (obj instanceof ComparatorForMinDistanceFirst) {
            var sc = (obj as ComparatorForMinDistanceFirst).spaceCraft;
            if (sc == spaceCraft) {
                return true;
            }
        }
        return false;
    }

}

class ComparatorForMaxDistanceFirst extends Comparator {
    var spaceCraft : SpaceCraftItem;
    var prg: Program;

    public override function compare(obj1:Object, obj2: Object):Integer{
        return sign (prg.distanceTime(spaceCraft, [(obj2 as ResourceItem)]) -
               prg.distanceTime(spaceCraft, [(obj1 as ResourceItem)]));
    }

    public override function equals(obj:Object) : Boolean {
        if (obj instanceof ComparatorForMaxDistanceFirst) {
            var sc = (obj as ComparatorForMaxDistanceFirst).spaceCraft;
            if (sc == spaceCraft) {
                return true;
            }
        }
        return false;
    }

}


Program{

    name: "Spacecraft_6_9"

    var startTrajectory: ResourceItem[];
    var firstStep: Boolean = true;
    var scanedMap: Boolean = false;
    var firstDistScan = false;
    var isFindFailed: Boolean = false;
    var resourcesSum: Number;
    var lastIndex = -1;
    var activeIndex = -1;
    var lastIndexCount = 0;

    def normalExpensiveScan: Number = 15;
    def percentIfNearestSpacecraft = 0.7;
    def percentIfNormalSpacecraft = 0.5;
    def percentIfFarSpacecraft = 0.3;
    def dist: Number = 3.0;
    def mistake = 500.0;
    def attemptsCount = 2;

    public override function setup():Void{
        if (sizeof map.spacecrafts > 0 and sizeof map.resources > 0) {

            resourcesSum = checkResourcesSum(map.resources);
            var spacecrafts = sizeof map.spacecrafts + 1;
            var startResourceForWint = resourcesSum / spacecrafts + 1;
            
            startTrajectory = findTrajectory(map.resources, startResourceForWint);
        }
    }

    function getPercentByDistance() : Number {
        var dist = getMinDistForMe(map.spacecrafts);
        if (dist < map.radius / 5) {
            return percentIfNearestSpacecraft;
        } else if (dist < map.radius / 3) {
            return percentIfNormalSpacecraft;
        } else {
            return percentIfFarSpacecraft;
        }
    }

    function getMinDistForMe(spaceCrafts: SpaceCraftItem[]) : Number {
        var minDist = Number.MAX_VALUE;
        for(spcr in spaceCrafts) {
            var dist = Point.distance(spcr, position);
            if(dist < minDist) {
                minDist = dist;
            }
        }
        return minDist;
    }

    function checkResourcesSum (resources: ResourceItem[]) : Number {
        var sum: Number = 0.0;
        for (resource in resources) {
            sum += resource.value;
        }
        return sum;
    }

    function isResourceAtSamePosition(resource: ResourceItem, resources: ResourceItem[]) : Boolean {
        for (item in resources) {
            if (Point.distance(item, resource) <= dist) {
                return true;
            }
        }
        return false;
    }

    function getTimeNearestResourceAndTime(startPoints: Point[], resources: ResourceItem[]): ResourceItemWithTime {
        var nearestResourceAndTime: ResourceItemWithTime;
        var minTime = Number.MAX_VALUE;

        for(resource in resources){
            var distTime = distanceTime([startPoints, resource]);
            if(distTime < minTime){
                minTime = distTime;
                nearestResourceAndTime = ResourceItemWithTime {time: distTime, resourceItem: resource};
            }
        }

        return nearestResourceAndTime;
    }

    function getMinTimeResorcesAndCoast(resources: ResourceItem[], needResourceSum: Number): OptimTimeForWinResourceCount {
        var copyOfResourceItems = resources;
        
        var minTimeDistance: ResourceItem[];
        var resultTime: Number = 0;
        var resultSum: Number = 0;
        var timeout: Boolean = false;
        var isEnoughResources: Boolean = false;
        var stopResource: ResourceItem = null;

        while (sizeof copyOfResourceItems > 0) {
            var nearestResourceAndTime = getTimeNearestResourceAndTime(minTimeDistance, copyOfResourceItems);
            delete nearestResourceAndTime.resourceItem from copyOfResourceItems;
            if (isResourceAtSamePosition(nearestResourceAndTime.resourceItem, minTimeDistance) == false) {
                if (isEnoughResources == false) {
                    resultTime = nearestResourceAndTime.time;
                }
                if (nearestResourceAndTime.time > map.gameTime - time) {
                    if (isEnoughResources == false) {
                        timeout = true;
                    }
                    break;
                }
                insert nearestResourceAndTime.resourceItem into minTimeDistance;
            }

            if (isEnoughResources == false) {
                resultSum += nearestResourceAndTime.resourceItem.value;
                if (resultSum > needResourceSum) {
                    isEnoughResources = true;
                    stopResource = nearestResourceAndTime.resourceItem;
                }
            }
        }

        return OptimTimeForWinResourceCount{stopResource: stopResource, 
                                            timeoutExit: timeout,
                                            time: resultTime,
                                            resourceSum: resultSum,
                                            resources: minTimeDistance};
    }

    function getNearestResourceAndCost(startPoints: Point[], resources: ResourceItem[]): ResourceItemWithTime {
        var resourceAndTime: ResourceItemWithTime;
        var maxCost: Number = Number.MIN_VALUE;
        var minTime: Number = Number.MAX_VALUE;

        for(resource in resources) {
            if (resource.value >= maxCost) {
                if (resource.value > maxCost) {
                    minTime = Number.MAX_VALUE;
                }

                maxCost = resource.value;
                var distTime = distanceTime([startPoints, resource]);

                if(distTime < minTime){
                    minTime = distTime;
                    resourceAndTime = ResourceItemWithTime{time: distTime, resourceItem: resource};
                }
            }
        }

        return resourceAndTime;
    }

    function getMostExpensiveResorcesAndCoast(resources: ResourceItem[], needResourceSum: Number): OptimTimeForWinResourceCount  {
        var copyOfResourceItems = resources;

        var distance: ResourceItem[];
        var resultTime: Number = 0;
        var resultSum: Number = 0;
        var timeout: Boolean = false;
        var isEnoughResources: Boolean = false;
        var stopResource: ResourceItem = null;

        while (sizeof copyOfResourceItems > 0) {
            var nearestResourceAndCost = getNearestResourceAndCost(distance, copyOfResourceItems);
            delete nearestResourceAndCost.resourceItem from copyOfResourceItems;
            if (isResourceAtSamePosition(nearestResourceAndCost.resourceItem, distance) == false) {
                if (isEnoughResources == false) {
                    resultTime = nearestResourceAndCost.time;
                }
                if (nearestResourceAndCost.time > map.gameTime - time) {
                    if (isEnoughResources == false) {
                        timeout = true;
                    }
                    break;
                }
                insert nearestResourceAndCost.resourceItem into distance;
            }

            if (isEnoughResources == false) {
                resultSum += nearestResourceAndCost.resourceItem.value;
                if (resultSum > needResourceSum) {
                    isEnoughResources = true;
                    stopResource = nearestResourceAndCost.resourceItem;
                }
            }
        }

        return OptimTimeForWinResourceCount{stopResource: stopResource, 
                                            timeoutExit: timeout,
                                            time: resultTime,
                                            resourceSum: resultSum,
                                            resources: distance};
    }

    function getDistanceNearestResource(startPoint: Point, resources: ResourceItem[]): ResourceItem {
        var nearestResource: ResourceItem;
        var minDist = Number.MAX_VALUE;

        for(resource in resources){
            var dist = Point.distance(startPoint, resource);
            if(dist < minDist){
                minDist = dist;
                nearestResource = resource;
            }
        }

        return nearestResource;
    }

    function getMinDistanceResorcesAndCoast(resources: ResourceItem[], needResourceSum: Number): OptimTimeForWinResourceCount {
        var copyOfResourceItems = resources;

        var minDistance: ResourceItem[];
        var timeout: Boolean = false;
        var isEnoughResources: Boolean = false;
        var resultTime: Number = 0;
        var resultSum: Number = 0;
        var nearestResource: ResourceItem = null;
        var stopResource: ResourceItem = null;

        while (sizeof copyOfResourceItems > 0) {
            if (nearestResource == null) {
                nearestResource = getDistanceNearestResource(position, copyOfResourceItems);
            } else {
                nearestResource = getDistanceNearestResource(nearestResource, copyOfResourceItems);
            }

            delete nearestResource from copyOfResourceItems;
            if (isResourceAtSamePosition(nearestResource, minDistance) == false) {
                var tempTime = distanceTime([minDistance, nearestResource]);
                if (isEnoughResources == false) {
                    resultTime = tempTime;
                }
                if (tempTime > map.gameTime - time) {
                    if (isEnoughResources == false) {
                        timeout = true;
                    }
                    break;
                }

                insert nearestResource into minDistance;
            }

            if (isEnoughResources == false) {
                resultSum += nearestResource.value;
                if (resultSum > needResourceSum) {
                    isEnoughResources = true;
                    stopResource = nearestResource;
                }
            }
        }

        return OptimTimeForWinResourceCount{stopResource: stopResource, 
                                            timeoutExit: timeout,
                                            time: resultTime,
                                            resourceSum: resultSum,
                                            resources: minDistance};
    }

    function getSpaceCraftsMinDistForResource(resource: ResourceItem, spaceCrafts: SpaceCraftItem[]): Number {
        var minDist = Number.MAX_VALUE;

        for(space in spaceCrafts){
            var dist = distanceTime(space, [resource]);
            if(dist < minDist){
                minDist = dist;
            }
        }
        return minDist;
    }

    function getNearestResorcesDist(resources: ResourceItem[], spaceCrafts: SpaceCraftItem[]): NearestDistForMeAndStranger {
        var resultResourcesForMe: ResourceItem[];
        var resultResourcesForStranger: ResourceItem[];
        var myDist: Number;
        var strangerDist: Number;

        for (resource in resources){
            myDist = distanceTime([resource]);
            strangerDist = getSpaceCraftsMinDistForResource(resource, spaceCrafts);
            if (myDist <= strangerDist) {
                insert resource into resultResourcesForMe;
            } else {
                insert resource into resultResourcesForStranger;
            }
        }
        return NearestDistForMeAndStranger {forMe: resultResourcesForMe, forStranger: resultResourcesForStranger};
    }

    function findTrajectory(inputRes: ResourceItem[], resourcesNeedForWin: Number): ResourceItem[] {
        
        if (sizeof inputRes < 2) return inputRes;

        var lineTrajectoryOptimTime = linearization(getMinTimeResorcesAndCoast(inputRes, resourcesNeedForWin));
        var lineTrajectoryOptimCost = linearization(getMostExpensiveResorcesAndCoast(inputRes, resourcesNeedForWin));
        var lineTrajectoryOptimDist = linearization(getMinDistanceResorcesAndCoast(inputRes, resourcesNeedForWin));
        
        var trajectory = null;
        var trajectoryExpireTime = null;
        var minTime = Number.MAX_VALUE;
        var maxCost = Number.MIN_VALUE;

        var optimTrajectorys: OptimTimeForWinResourceCount[] = [lineTrajectoryOptimTime, lineTrajectoryOptimCost, lineTrajectoryOptimDist];

        for (item in optimTrajectorys) {
            if (item.timeoutExit == false) {
                if (item.time < minTime) {
                    trajectory = item;
                    minTime = item.time;
                }
            } else {
                if (item.resourceSum > maxCost) {
                    trajectoryExpireTime = item;
                    maxCost = item.resourceSum;
                }
            }
        }

        if (trajectory != null) {
            return trajectory.resources;
        } else {
            return trajectoryExpireTime.resources;
        }
    }

    function isOnLine(p1:Point, p2:Point, p3:Point): Boolean {
        var result = (p3.x - p1.x) * (p2.y - p1.y) - (p3.y - p1.y) * (p2.x - p1.x);

        return Math.abs(result) < mistake;
    }

    function linearization(trajectory: OptimTimeForWinResourceCount): OptimTimeForWinResourceCount{
        
        if (sizeof trajectory.resources < 2) return trajectory;

        var time: Number = 0.0;
        var linerizeResources: ResourceItem[];
        var p1: Point = position;
        var p2: Point = trajectory.resources[0];
        var p3: Point;
        var wasStopResource: Boolean = false;

        for (item in trajectory.resources[1..]) {
            if (trajectory.stopResource == item) {
                wasStopResource = true;
            }

            p3 = item;
            if (isOnLine(p1, p2, p3)) {
                p2 = p3;
            } else {
                insert (p2 as ResourceItem) into linerizeResources;
                p1 = p2;
                p2 = p3;

                if (wasStopResource == true) {
                    wasStopResource = false;
                    time = distanceTime(linerizeResources);
                }
            }
        }

        insert (p3 as ResourceItem) into linerizeResources;

        if (time == 0.0) {
            time = distanceTime(linerizeResources);
        }
        
        return OptimTimeForWinResourceCount{timeoutExit: trajectory.timeoutExit, time: time, resourceSum: trajectory.resourceSum, resources: linerizeResources};
    }

    function generateStrategy(resources: ResourceItem[], spaceCrafts: SpaceCraftItem[]): ResourceItem[] {
        var resultTrajectory: ResourceItem[];
        var nearestResoruces = getNearestResorcesDist(resources, spaceCrafts);
        
        var myNearestResorcesSum = checkResourcesSum(nearestResoruces.forMe);
        var resourcesNeedForWin = Math.round(resourcesSum / 2) - score + 1;
        
        if (isFindFailed == false) {
            return findTrajectory(nearestResoruces.forMe, resourcesNeedForWin);
        }

        if (myNearestResorcesSum >= resourcesNeedForWin) {
            resultTrajectory = findTrajectory(nearestResoruces.forMe, resourcesNeedForWin);
        } else if (sizeof resources < 3) {
            var lastResources: ResourceItem[] = nearestResoruces.forMe;
            if (sizeof nearestResoruces.forMe == 0) {
                var sortedResourceForStranger = Sequences.sort(nearestResoruces.forStranger,
                                    ComparatorForMinDistanceFirst{prg: this, spaceCraft: map.spacecrafts[0]}) as ResourceItem[];

                if (sizeof sortedResourceForStranger > 1) {
                    lastResources = [sortedResourceForStranger[1]];
                }
            }
            resultTrajectory = findTrajectory(lastResources, resourcesNeedForWin);
        } else if (getMinDistForMe(map.spacecrafts) < map.radius / 5) {

            var sortedResourceForStranger = Sequences.sort(nearestResoruces.forStranger,
                                    ComparatorForMaxDistanceFirst{prg: this, spaceCraft: map.spacecrafts[0]}) as ResourceItem[];

            var countOfNearestResourcesForStraner = sizeof nearestResoruces.forStranger;
            var percentOfStartElementCount = getPercentByDistance();
            var elementsCountFromStrangerNearestResources: Integer = Math.round(percentOfStartElementCount * countOfNearestResourcesForStraner);
            var resorcesForTrajectoryResearch: ResourceItem[] = [nearestResoruces.forMe, sortedResourceForStranger[0..<elementsCountFromStrangerNearestResources]];

            resultTrajectory = findTrajectory(resorcesForTrajectoryResearch, resourcesNeedForWin);
        } else {
            resultTrajectory = findTrajectory(nearestResoruces.forMe, resourcesNeedForWin);
        }

        if (sizeof resultTrajectory > 0) {
            return resultTrajectory;
        } else {
            return findTrajectory(resources, Number.MAX_VALUE);
        }
    }

    public override function nextStep():Action{

        if (action == null) {
            if (firstStep) {
                firstStep = false;
                return MoveAction{path: startTrajectory};
            } else {
                if (scanedMap) {
                    scanedMap = false;

                    var scanedResources = generateStrategy(map.resources, map.spacecrafts);

                    return MoveAction{path: scanedResources};
                } else {
                    scanedMap = true;
                    return SpaceScanAction{};
                }
            }
        } else {
            if (action instanceof MoveAction) {
                var act : MoveAction = action as MoveAction;
                var activeResource = act.path[act.pathIndex] as ResourceItem;
                
                var cont = map.containResource(activeResource);

                if (not cont) {
                    if (act.pathIndex == lastIndex and lastIndexCount > attemptsCount) {
                        lastIndex = -1;
                        lastIndexCount = 0;
                        firstStep = false;
                        isFindFailed = true;
                        scanedMap = true;
                        return SpaceScanAction{};
                    } else {
                        lastIndex = act.pathIndex;
                        lastIndexCount++;
                    }
                } else {
                    lastIndexCount = 0;
                    lastIndex = -1;
                }

                if (act.pathIndex > 0 and act.pathIndex != activeIndex and map.skip_time < normalExpensiveScan) {
                    if (firstDistScan == false and act.pathIndex < 2) {
                        firstDistScan = true;
                    } else if (Point.distance(act.path[act.pathIndex  - 1], act.path[act.pathIndex]) > map.radius / 3) {
                        scanedMap = true;
                        return SpaceScanAction{};
                    }
                }
                activeIndex = act.pathIndex;
            }
        }

        return null;
    }
}

О компании  |  Торговые марки  |  Copyright 2009 Sun Microsystems Inc.