Sun
SDK: 1.44


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


Царь Горы  »

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

SDK 1.43  »

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

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

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

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

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

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

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

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

  • Это вторая Ваша победа. Было сложно победить? Сколько времени у вас отнимает участие в конкурсе?
    Времени тратил примерно столько же, как и в первом туре: несколько часов после работы, иногда больше. Что касается сложности победы, то давление со стороны игроков, занявших 2 и 3 места, ощущалось, что стимулировало к улучшению алгоритма.

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

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

  • Как вы относитесь к изменениям игрового мира между этапами?
    Изменения, безусловно, должны быть, иначе бы все слилось в один тур. После каждого тура приходилось вносить серьезные корректировки в алгоритм.

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

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

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

  • Чем привлекает Вас JavaFX и что как Вам кажется стоит улучшить?
    Для создания алгоритмов я использую небольшую часть возможностей языка, поэтому не могу быть экспертом в данном вопросе. Привлекательно выглядят примеры RIAs, представленные на http://javafx.com. Что касается меня, то мне иногда удобно использовать тернарный условный оператор. Если дозволено использовать коллекции Java, то неплохо было бы включить и поддержку шаблонов.

  • Планируете ли Вы применять JavaFX в дальнейшем? Если да, то как?
    Сложный вопрос, язык еще достаточно молодой, и нацелен, в первую очередь, на Интернет, где у него есть сильные конкуренты. Возможно, это будут студенческие учебные проекты, в которых также скорее всего будет участвовать и Sun Spot Development Kit.

  • Надеетесь победить в финале?
    Думаю, это цель каждого участвующего в конкурсе.

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

 

Результаты состязаний по дням
2009-12-04
2009-12-03
2009-12-02
2009-12-01
2009-11-30
2009-11-29
2009-11-28
2009-11-27
2009-11-26
2009-11-25
2009-11-24
2009-11-23
2009-11-22
2009-11-21
2009-11-20
2009-11-19
2009-11-18
2009-11-17
2009-11-16
2009-11-15
2009-11-14
2009-11-13
2009-11-12
2009-11-11
2009-11-10
2009-11-09
2009-11-08
2009-11-07
2009-11-06
2009-11-05
2009-11-04
2009-11-03
2009-11-02
2009-11-01
2009-10-31
2009-10-30
2009-10-29
2009-10-28
2009-10-27
2009-10-26
2009-10-25
2009-10-24
2009-10-23
2009-10-22
2009-10-21
2009-10-20
2009-10-19
2009-10-18
2009-10-17
2009-10-16
2009-10-15
2009-10-14
2009-10-13
2009-10-12
2009-10-11
2009-10-10
2009-10-09
2009-10-08
2009-10-07
2009-10-06
2009-10-05
2009-10-01
2009-09-30
2009-09-29
2009-09-28
2009-09-27
2009-09-26
2009-09-25
2009-09-24
2009-09-23
2009-09-22
2009-09-21
2009-09-20
2009-09-19
2009-09-18
2009-09-17
2009-09-16
2009-09-15
2009-09-14
2009-09-13
2009-09-12
2009-09-11
2009-09-03
2009-08-31
2009-08-30
2009-08-29
2009-08-02
2009-08-01
2009-07-31
2009-07-30
2009-07-29
2009-07-28
2009-07-27
2009-07-26
2009-07-25
2009-07-24
2009-07-23
2009-07-22
2009-07-21
2009-07-20
2009-07-19
2009-07-18
2009-07-17
2009-07-16
2009-07-15
2009-07-14

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

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 galaxyfx.spacecraft.system.CargoTerminalItem;

import java.util.HashMap;

class SpaceCraftAndResourceOnLine {
    var spaceCraft: SpaceCraftItem;
    var resourceOnLine: ResourceItem;
}

class OptimTimeForWinResourceCount {
    var timeoutExit: Boolean;
    var time: Number;
    var coast: Number;
    var action: CompoundAction;
}

class ResourceAndTime {
    var resource: ResourceItem;
    var timeForMe: Number;
    var timeForStranger: Number;
}

class NearestDistForMeAndStranger {
    var forMe: ResourceAndTime[];
    var forStranger: ResourceAndTime[];

    function getNearestForMe(): ResourceItem[] {
        var res: ResourceItem[];
        for(item in forMe) {
            insert item.resource into res;
        }
        return res;
    }

    function getNearestForStranger(): ResourceItem[] {
        var res: ResourceItem[];
        for(item in forStranger) {
            insert item.resource into res;
        }
        return res;
    }
}

class NearestTerminal {
    var pos: CargoTerminalItem;
    var time: Number;
}

class SpaceCraftLastPosition {
    var spaceCraft: SpaceCraftItem;
    var isMoved: Boolean = false;
}

var terminals: CargoTerminalItem[];
var locCargoCapacity: Number;
var gameTime: Number;
var harvestTimeMap: HashMap;
var lastSpPositionMap: HashMap = new HashMap();

function copySpaceCraftItems(spaceCrafts: SpaceCraftItem[]): Void {
    for(sp in spaceCrafts) {
        var obj = lastSpPositionMap.get(sp.id);
        if (obj instanceof SpaceCraftLastPosition) {
            (obj as SpaceCraftLastPosition).spaceCraft = sp.copy();
        } else {
            lastSpPositionMap.put(sp.id, SpaceCraftLastPosition{spaceCraft: sp.copy()});
        }
    }
}

function isSpaceCraftNotMove(sp: SpaceCraftItem): Boolean {
    var result: Boolean = false;
    var obj = lastSpPositionMap.get(sp.id);
    if (obj instanceof SpaceCraftLastPosition) {
        var spLastPosition = (obj as SpaceCraftLastPosition);
        var isMoved = Point.distance(sp, spLastPosition.spaceCraft) >  20;
        if (not isMoved and not spLastPosition.isMoved){
            result = true;
        }
        spLastPosition.isMoved = isMoved;
    }
    return result;
}

function findNearestTerminal(pos: Point): NearestTerminal {
    var minDist: Number = Number.MAX_VALUE;
    var nearestTerminal: CargoTerminalItem;
    var dist: Number;

    for (term in terminals) {
        dist = Point.distance(pos, term);
        if (dist < minDist) {
            minDist = dist;
            nearestTerminal = term;
        }
    }
    return NearestTerminal{pos: nearestTerminal, time: minDist};
}

function calculateHarvestTime(resources: ResourceItem[]): Number {
    var tempValue;
    var harvestTime: Number = 0.0;
    for(res in resources) {
        tempValue = harvestTimeMap.get(res.value);
        if (tempValue != null) {
            harvestTime += tempValue as Number;
        }
    }
    return harvestTime;
}

function createUnloadActions(point: Point): Action[] {
    var nearestTerminal = findNearestTerminal(point).pos;
    return [MoveAction {path: [nearestTerminal]}, UnloadAction {}];
}
function createUnloadActions(spaceCraft: Point, unloadCargo: Number): Action[] {
    var nearestTerminal = findNearestTerminal(spaceCraft).pos;
    return [MoveAction {path: [nearestTerminal]}, UnloadAction {limit:unloadCargo}];
}
function createHarvestActions(resource: ResourceItem, loadCargo: Number): Action[] {
    return [MoveAction{path: [resource]}, HarvestAction{limit: loadCargo, target: resource}];
}

abstract class TrajectoryResearcher {

    var prg: Program;

    public abstract function findOptimResource(includedPoints: Point[], resources: ResourceItem[]): ResourceItem;
    public abstract function findOptimTrafectory(resources: ResourceItem[], startPoint: ResourceItem): OptimTimeForWinResourceCount;

    public function findTrafectorys(resources: ResourceItem[], startPoints: Integer): OptimTimeForWinResourceCount[] {
        var points = startPoints;
        var copyOfResources = resources;
        var result: OptimTimeForWinResourceCount[];
        var startItem: ResourceItem = null;

        if (points > sizeof resources) {
            points = sizeof resources;
        }

        if (points > 1) {
            while (points-- > 0) {
                startItem = findOptimResource([], copyOfResources);
                delete startItem from copyOfResources;
                insert findOptimTrafectory(resources[item | not item.equals(startItem)], startItem) into result;
            }
        } else {
            insert findOptimTrafectory(resources, startItem) into result;
        }

        return result;
    }

    function trajectoryTime(res:ResourceItem[]): Number {
        var lastPointBeforeTerminal: Point;
        if (sizeof res > 0) {
            lastPointBeforeTerminal = res[sizeof res - 1];
        } else {
            lastPointBeforeTerminal = prg.position;
        }

        var time = prg.distanceTime([res, findNearestTerminal(lastPointBeforeTerminal).pos]);
        time += 20 + calculateHarvestTime(res);
        return time;
    }

    public function generateCompoundAction(res:ResourceItem[]): CompoundAction {
        var lastPointBeforeTerminal: Point;
        var compoundAction = CompoundAction {};

        if (sizeof res > 0) {
            lastPointBeforeTerminal = res[sizeof res - 1];
            for(item in res) {
                insert createHarvestActions(item, item.value) into compoundAction.actions;
            }
        } else {
            lastPointBeforeTerminal = prg.position;
        }

        insert createUnloadActions(lastPointBeforeTerminal) into compoundAction.actions;
        return compoundAction;
    }
}

abstract class TrajectoryForSpacecraft extends TrajectoryResearcher {

    public override function findOptimTrafectory(resources: ResourceItem[], startPoint: ResourceItem): OptimTimeForWinResourceCount {
        var copyOfResourceItems = resources;

        var minTimeDistance: ResourceItem[];
        var resultTime: Number;
        var resultSum: Number = prg.cargo;
        var timeout: Boolean = false;

        if (startPoint != null) {
            var distTime = trajectoryTime([startPoint]);
            if (distTime > gameTime - prg.time) {
                return OptimTimeForWinResourceCount{timeoutExit: true,
                                            time: trajectoryTime([]),
                                            coast: resultSum,
                                            action: generateCompoundAction([])};
            }

            resultTime = distTime;
            resultSum += startPoint.value;
            insert startPoint into minTimeDistance;
        }

        while (sizeof copyOfResourceItems > 0) {
            if (resultSum >= locCargoCapacity) {
                break;
            }

            var resource = findOptimResource(minTimeDistance, copyOfResourceItems);
            delete resource from copyOfResourceItems;

            var distTime = trajectoryTime([minTimeDistance, resource]);

            if (distTime > gameTime - prg.time) {
                timeout = true;
                break;
            }

            insert resource into minTimeDistance;
            resultTime = distTime;
            resultSum += resource.value;
        }
        
        return OptimTimeForWinResourceCount{timeoutExit: timeout,
                                            time: resultTime,
                                            coast: resultSum,
                                            action: generateCompoundAction(minTimeDistance)};
    }
}

class TimeForSpacecraft extends TrajectoryForSpacecraft {
    public override function findOptimResource(includedPoints: Point[], resources: ResourceItem[]): ResourceItem {
        var nearestResource: ResourceItem;
        var minTime = Number.MAX_VALUE;

        for(resource in resources){
            var distTime = prg.distanceTime([includedPoints, resource]);
            if(distTime < minTime){
                minTime = distTime;
                nearestResource = resource;
            }
        }
        return nearestResource;
    }
}

class FactorOptimForSpacecraft extends TrajectoryForSpacecraft {
    
    var timeWeight: Number;
    var costWeight: Number;

    init {
        costWeight = 1.0 - timeWeight;
    }

    public override function findOptimResource(includedPoints: Point[], resources: ResourceItem[]): ResourceItem {
        var costSum: Number = 0;
        var timeSum: Number = 0;
        var distTime: Number = 0;
        var minDistTime:Number = Number.MAX_VALUE;
        var minTimeDistResource: ResourceItem;
        var criterion;
        var maxCriterion: Number = Number.MIN_VALUE;
        var criterionTime: Number;
        var foundResource: ResourceItem;
        
        for(resource in resources) {
            distTime = prg.distanceTime([includedPoints, resource]);

            costSum += resource.value;
            timeSum += 1 / distTime;

            if (resource.value >= locCargoCapacity - prg.cargo and distTime < minDistTime) {
                minDistTime = distTime;
                minTimeDistResource = resource;
            }
        }
        
        for(resource in resources) {
            distTime = prg.distanceTime([includedPoints, resource]);
            criterion = costWeight * resource.value / costSum + timeWeight / (distTime *  timeSum);

            if (criterion > maxCriterion) {
                maxCriterion = criterion;
                criterionTime = distTime;
                foundResource = resource;
            }
        }

        if (minDistTime < criterionTime) {
            foundResource = minTimeDistResource;
        }

        return foundResource;
    }
}

Program {
    name: "Spacecraft_0_6"

    autoHarvest: false;

    options: TuningOptions {
        cargo: 1,
        speed: 3,
        teamwork: 0,
        radar: 0
    }

    var startCompoundAction: CompoundAction;
    var spacecrafts: Integer;
    var firstStep: Boolean = true;
    var scanedMap: Boolean = false;
    var resourcesSum: Number;
    var lastScanTime: Number = 0;

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

            terminals = map.terminals;
            locCargoCapacity = 120;
            gameTime = map.gameTime;
            harvestTimeMap = setupHarvestMap(map.resources);
            
            resourcesSum = checkResourcesSum(map.resources);

            startCompoundAction = generateStrategy(map.resources, map.spacecrafts);
        }
    }

    function setupHarvestMap(resources: ResourceItem[]): HashMap {
        var time;
        var tempValue;
        var mapValueTime: HashMap = new HashMap();
        
        for(res in resources) {
            tempValue = mapValueTime.get(res.value);
            if (tempValue == null) {
                time = timeToComplete(CompoundAction{actions: createHarvestActions(res, res.value)}, null)-
                        timeToComplete(CompoundAction{actions:MoveAction{path: [res]}}, null);

                if (time <= 0) time = 5.0;

                mapValueTime.put(res.value, time);
            }
        }
        return mapValueTime;
    }

    function isStarFromOnePosition(spaceCrafts: SpaceCraftItem[]): Boolean {
        for(spcr in spaceCrafts) {
            if (not isSpaceCraftNotMove(spcr) and Point.distance(spcr, position) > 10) {
                return false;
            }
        }
        return true;
    }

    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 getSpaceCraftsMinDistForResource(resource: ResourceItem, spaceCraftAndResourceOnLine: SpaceCraftAndResourceOnLine[]): Number {
        var minDist: Number = Number.MAX_VALUE;
        var dist: Number;

        for(space in spaceCraftAndResourceOnLine){
            if (space.resourceOnLine == null) {
                dist = distanceTime(space.spaceCraft, [resource]);
            } else {
                dist = distanceTime(space.spaceCraft, [space.resourceOnLine, resource]);
            }

            if(dist < minDist){
                minDist = dist;
            }
        }
        return minDist;
    }

    def fault: Number = 1e-6;
    function getResourceOnLine(resources: ResourceItem[], spaceCraft: SpaceCraftItem): ResourceItem {
        var tan = Math.tan(spaceCraft.direction);
        var localDirection = 0.0;
        var x = spaceCraft.x;
        var y = spaceCraft.y;
        var y_sign = 0.0;
        var x_sign = 0.0;
        var minDist: Number = Number.MAX_VALUE;
        var foundResource: ResourceItem = null;

        var checkResourceDist = function (item: ResourceItem):Void{
            var dist = Point.distance(spaceCraft, item);
            if (dist < minDist) {
                minDist = dist;
                foundResource = item;
            }
        };

        if (spaceCraft.direction < -Math.PI) {
            localDirection = 2*Math.PI + spaceCraft.direction;
        } else if(spaceCraft.direction > Math.PI) {
            localDirection = -2*Math.PI + spaceCraft.direction;
        } else {
            localDirection = spaceCraft.direction;
        }

        for (item in map.resources) {
            x_sign = item.x - x;
            y_sign = item.y - y;
            if (Math.abs(x_sign) < fault and Math.abs(Math.abs(localDirection) - Math.PI / 2) < fault) {
                if ((y_sign >= 0 and localDirection > 0) or (y_sign <= 0 and localDirection < 0)) {
                    checkResourceDist(item);
                }
            } else if (Math.abs(y_sign) < fault) {
                if ((Math.abs(Math.abs(localDirection) - Math.PI) < fault and x_sign <= 0) or
                    (Math.abs(localDirection) < fault and x_sign >= 0)) {
                    checkResourceDist(item);
                }
            } else {
                var value = (x_sign) * tan - (y_sign);
                if (Math.abs(value) < 0.1 and
                    ((y_sign >= 0 and localDirection > 0) or (y_sign <= 0 and localDirection < 0))) {
                    checkResourceDist(item);
                }
            }
        }
        return foundResource;
    }

    function getSpaceCraftsWithResourceOnLine(resources: ResourceItem[], spaceCrafts: SpaceCraftItem[]): SpaceCraftAndResourceOnLine[]{
        var result: SpaceCraftAndResourceOnLine[];
        var resourceOnLine: ResourceItem;

        for(sp in spaceCrafts) {
            resourceOnLine = getResourceOnLine(resources, sp);
            insert SpaceCraftAndResourceOnLine{spaceCraft: sp, resourceOnLine: resourceOnLine} into result;
        }

        return result;
    }

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

        var spaceCraftAndResourceOnLine = getSpaceCraftsWithResourceOnLine(resources, spaceCrafts[sp|not isSpaceCraftNotMove(sp)]);

        for (resource in resources) {
            myDist = distanceTime([resource]);
            strangerDist = getSpaceCraftsMinDistForResource(resource, spaceCraftAndResourceOnLine);
            if (myDist <= strangerDist) {
                insert ResourceAndTime{resource: resource, timeForMe: myDist, timeForStranger: strangerDist} into resultResourcesForMe;
            } else {
                sizeSecStranger = sizeof resultResourcesForStranger;
                for(resForStranger in resultResourcesForStranger) {
                    if (resForStranger.timeForStranger > strangerDist) {
                        insert ResourceAndTime{resource: resource, timeForMe: myDist, timeForStranger: strangerDist} before resultResourcesForStranger[indexof resForStranger];
                        break;
                    }
                }

                if (sizeSecStranger == sizeof resultResourcesForStranger) {
                    insert ResourceAndTime{resource: resource, timeForMe: myDist, timeForStranger: strangerDist} into resultResourcesForStranger;
                }
            }
        }

        return NearestDistForMeAndStranger {forMe: resultResourcesForMe, forStranger: resultResourcesForStranger};
    }

    function findTrajectory(inputRes: ResourceItem[]): OptimTimeForWinResourceCount {
        
        var trajectoryOptimTime = TimeForSpacecraft{prg: this}.findTrafectorys(inputRes, 3);
        var trajectoryFactorOptim = FactorOptimForSpacecraft{prg: this, timeWeight: 0.7}.findTrafectorys(inputRes, 3);

        var trajectoryMaxCoast: OptimTimeForWinResourceCount[];
        if (isStarFromOnePosition(map.spacecrafts)) {
            trajectoryMaxCoast = [
                FactorOptimForSpacecraft{prg: this, timeWeight: 0.2}.findTrafectorys(inputRes, 2),
                FactorOptimForSpacecraft{prg: this, timeWeight: 0.4}.findTrafectorys(inputRes, 2)];
        }

        var trajectory = null;
        var trajectoryExpireTime = null;
        var minTime = Number.MAX_VALUE;
        var maxCost = Number.MIN_VALUE;

        var optimTrajectorys: OptimTimeForWinResourceCount[] = [trajectoryOptimTime,
                                                                trajectoryFactorOptim,
                                                                trajectoryMaxCoast];

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

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

    function needTermination(start: Point, stop:Point): CargoTerminalItem {
        var dist = Point.distance(start, stop);
        var a = stop.y - start.y;
        var b = start.x - stop.x;
        var c = -(start.y * b + start.x * a);

        for (term in map.terminals) {
            var distForStartPoint = Point.distance(start, term);
            var distForStopPoint = Point.distance(term, stop);
            var d = Math.abs(a * term.x + b * term.y + c) / Math.sqrt(a * a + b * b);

            if (distForStartPoint <= dist and distForStopPoint <= dist and d <= dist / 4 and
               (score + cargo) < resourcesSum * 0.3 and cargo > locCargoCapacity * 0.85) {

                return term;
            }
        }

        return null;
    }

    function generateStrategy(resources: ResourceItem[], spaceCrafts: SpaceCraftItem[]): CompoundAction {
        stepAfterScan = 0;

        var resultTrajectory: CompoundAction;
        var nearestResoruces = getNearestResorcesDist(resources, spaceCrafts);
        var myNearestResorcesSum = checkResourcesSum(nearestResoruces.getNearestForMe());
        var resourcesNeedForWin = (resourcesSum / 2 + 1) - (score + cargo);
        var resourcesNeedForFullCargo = locCargoCapacity - cargo;
        
        if (sizeof resources < 3) {
            var lastResources: ResourceItem[] = nearestResoruces.getNearestForMe();
            if (sizeof nearestResoruces.forMe == 0) {
                if (sizeof nearestResoruces.forStranger > 1) {
                    lastResources = [nearestResoruces.getNearestForStranger()[1]];
                } else {
                    lastResources = [nearestResoruces.getNearestForStranger()[0]];
                }
            }
            resultTrajectory = findTrajectory(lastResources).action;
        } else if (myNearestResorcesSum > resourcesNeedForWin) {
            resultTrajectory = findTrajectory(nearestResoruces.getNearestForMe()).action;
        } else {
            var resourceForStranger  = nearestResoruces.getNearestForStranger();
            var countResForStranger = sizeof resourceForStranger;
            if (countResForStranger > 3) {
                resourceForStranger = resourceForStranger[2..];
            } else if (countResForStranger > 2) {
                resourceForStranger = resourceForStranger[1..];
            }

            if (myNearestResorcesSum * 0.8 > checkResourcesSum(resourceForStranger)) {
                resultTrajectory = findTrajectory([nearestResoruces.getNearestForMe()]).action;
            } else {
                resultTrajectory = findTrajectory([nearestResoruces.getNearestForMe(), resourceForStranger]).action;
            }
        }

        copySpaceCraftItems(spaceCrafts);
        return resultTrajectory;
    }

    function isStrangerSpaceCraftOnResourceItem(spaceCrafts: SpaceCraftItem[], resource: ResourceItem ): Boolean {
        for (sp in spaceCrafts) {
            if (sp.x == resource.x and sp.y == resource.y) {
                return true;
            }
        }
        return false;
    }

    function isShortStep(compoundAction: CompoundAction): Boolean {
        if (compoundAction.actions[0] instanceof MoveAction) {
            var moveAction = compoundAction.actions[0] as MoveAction;
            if (Point.distance(position, moveAction.path[0]) < map.radius / 4) {
                return true;
            }
        }
        return false;
    }

    function isTerminalStep(compoundAction: CompoundAction) : Boolean {
        if (sizeof compoundAction.actions > 2) {
            return false;
        }
        return true;
    }

    function generateSpaceScanAction (): Action  {
        var timeAfterScan = time - map.timestamp;
        if (timeAfterScan <= 30) {
            return generateStrategy(map.resources, map.spacecrafts);
        } else if (timeAfterScan <= 50) {
            var compoundAction = generateStrategy(map.resources, map.spacecrafts);
            if (isShortStep(compoundAction)) {
                return compoundAction;
            }
        } 
        return SpaceScanAction{};
    }

    var lastActiveResource: ResourceItem = null;
    var isCargoTerminal: Boolean = false;
    var stepAfterScan: Integer = 0;

    public override function nextStep():Action{
        if (action == null) {
            locCargoCapacity = cargoCapacity;

            if (firstStep) {
                firstStep = false;
                return startCompoundAction;
            } else {
                if (scanedMap) {
                    scanedMap = false;
                    return generateStrategy(map.resources, map.spacecrafts);
                } else {
                    return generateSpaceScanAction();
                }
            }
        } else {
            if (action instanceof CompoundAction) {
                var act : CompoundAction = action as CompoundAction;
                var curAction = act.actions[act.currentIndex];

                if (curAction instanceof MoveAction) {
                    var moveAction: MoveAction = curAction as MoveAction;
                    var currentPosition = moveAction.path[moveAction.pathIndex];

                    if (currentPosition instanceof ResourceItem) {
                        isCargoTerminal = false;
                        var activeResource = currentPosition as ResourceItem;

                        if (not map.containResource(activeResource)) {
                            if (sizeof radar.spacecrafts > 0) {
                                var compoundAction = generateStrategy(map.resources, radar.spacecrafts);
                                if (isShortStep(compoundAction) and not isTerminalStep(compoundAction)) {
                                    return compoundAction;
                                }
                            }
                            return SpaceScanAction{};
                        }
                        
                        if (not activeResource.equals(lastActiveResource)) {
                            if (lastActiveResource != null) {
                                var terminal = needTermination(lastActiveResource, activeResource);
                                if (terminal != null) {
                                    isCargoTerminal = true;
                                    return CompoundAction{actions: [createUnloadActions(terminal)]};
                                }
                            }

                            var pointsDist = Point.distance(position, activeResource);
                            if ((stepAfterScan > 1 and pointsDist > map.radius * 0.6 and (sizeof radar.spacecrafts) == 0) or
                                (stepAfterScan > 0 and pointsDist > map.radius * 1.0)) {
                                if (sizeof radar.resources > 0) {
                                    var compoundAction = generateStrategy(radar.resources, radar.spacecrafts);
                                    if (not isTerminalStep(compoundAction)) {
                                        return compoundAction;
                                    }
                                    return generateSpaceScanAction();
                                } else {
                                    return generateSpaceScanAction();
                                }
                            }
                            stepAfterScan++;
                        }
                        lastActiveResource = activeResource;
                        
                    } else if (currentPosition instanceof CargoTerminalItem and
                               sizeof map.resources > 0 and not isCargoTerminal)  {
                        var resSum = checkResourcesSum(map.resources);
                        if((locCargoCapacity - cargo >= resSum * 0.2) or
                         (cargo < locCargoCapacity * 0.85) or
                         (findNearestTerminal(position).time > map.radius * 0.3 and cargo < locCargoCapacity * 0.9)) {
                            isCargoTerminal = true;
                            resSum = checkResourcesSum(radar.resources);
                            if (resSum > 0) {
                                var compoundAction = generateStrategy(radar.resources, radar.spacecrafts);
                                if (not isTerminalStep(compoundAction)) {
                                    return compoundAction;
                                }
                                return generateSpaceScanAction();
                            } else {
                                return generateSpaceScanAction();
                            }
                        }
                    }
                } else if (curAction instanceof HarvestAction) {
                    var harvestAction: HarvestAction = curAction as HarvestAction;
                    var limit: Number;

                    if (lastActiveResource.value <= 10) {
                        limit = lastActiveResource.value * 0.75;
                    } else {
                        limit = lastActiveResource.value / 2;
                    }

                    if (harvestAction.limit <= limit and isStrangerSpaceCraftOnResourceItem(radar.spacecrafts, lastActiveResource) and sizeof map.resources > 2) {
                        var radarResources = radar.resources[item | not item.equals(lastActiveResource)];
                        var resSum = checkResourcesSum(radarResources);
                        if (resSum >= (locCargoCapacity - cargo) / 2) {
                            var compoundAction = generateStrategy(radar.resources, radar.spacecrafts);
                            if (not isTerminalStep(compoundAction)) {
                                return compoundAction;
                            }
                            return generateSpaceScanAction();
                        }
                    }
                } else if (curAction == null) {
                    return generateSpaceScanAction();
                }
            } else if (action instanceof SpaceScanAction) {
                scanedMap = true;
            }
        }
        return null;
    }
}

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