// CONSTANTS

let _myCyborgs; let _enemyCyborgs; let _myProd; let _enemyProd;

///PARSEAR READLINE

var _factoryCount = parseInt(readline()); var _factories = {}; var _myFactories, _enemyFactories, _neutralFactories, _maxEta;

var _distances = { 'get': function( id1, id2 ){ if( id1 < id2 ){ return this[id1][id2]; } if( id1 > id2 ){ return this[id2][id1]; } return 0; } }; var _maxDistance = 0; for( var i=0; i < _factoryCount; i++ ){ _distances[i] = {}; }

var linkCount = parseInt(readline()); for (var i = 0; i < linkCount; i++) { var inputs = readline().split(' '); var f1 = parseInt(inputs[0]); var f2 = parseInt(inputs[1]); var distance = parseInt(inputs[2]); _distances[f1][f2] = distance;

if( distance > _maxDistance ){ _maxDistance = distance; }

}

var _bombCount = 2; var _enemyBombs, _enemyBombedFactories; var _enemyBombLive = { };

/// MAIN LOOP

while (true) {

// CONSTANTS LOOP

_myCyborgs = 0;
_enemyCyborgs = 0;
_myProd = 0;
_enemyProd = 0;
_myFactories = [];
_enemyFactories = [];
_neutralFactories = [];
_enemyBombs = [];
_enemyBombedFactories = [];
_maxEta = 0;


// READLINE LOOP

var entityCount = parseInt(readline()); 
for( var i = 0; i < entityCount; i++ ){
    var inputs = readline().split(' ');
    var entityId = parseInt(inputs[0]);
    var entityType = inputs[1];
    var arg1 = parseInt(inputs[2]);
    var arg2 = parseInt(inputs[3]);
    var arg3 = parseInt(inputs[4]);
    var arg4 = parseInt(inputs[5]);
    var arg5 = parseInt(inputs[6]);


    // FACTORY
    if( entityType === 'FACTORY' ){
        var f = {
            'id': entityId,
            'cyborgs': arg2, 
            'owner': arg1,
            'production': arg3,
            'tbnp': arg4 
        };

        if( f.owner === 1 ){
            _myFactories.push( f.id );
            _myCyborgs += f.cyborgs;
            _myProd += f.production;
        }
        else if( f.owner === -1 ){
            _enemyFactories.push( f.id );
            _enemyCyborgs += f.cyborgs;
            _enemyProd += f.production;
        }
        else {
            _neutralFactories.push( f.id );
        }

        // TIPO
        f.incomings = {
            'allies': {
                'max': 0
            },
            'enemies': {
                'max': 0
            },
            'add': function( turns, number, ally ){
                var sub = ally ? 'allies' : 'enemies';
                if( !this[sub][turns] ){
                    this[sub][turns] = 0;
                }
                this[sub][turns] += number;
                if( turns > this[sub]['max'] ){
                    this[sub]['max'] = turns;
                }
                if( turns > _maxEta ){
                    _maxEta = turns;
                }
            }
        };

        _factories[entityId] = f;
    }

    /// LOGICA TROOP
    else if( entityType === 'TROOP' ){
        var t = {
            'owner': arg1,
            'src': arg2,
            'dest': arg3,
            'cyborgs': arg4,
            'eta': arg5
        };
        var destFactory = _factories[arg3];
        destFactory.incomings.add( t.eta, t.cyborgs, t.owner === 1 );

        if( t.owner === 1 ){
            _myCyborgs += t.cyborgs;
        }
        else if( t.owner === -1 ){
            _enemyCyborgs += t.cyborgs;
        }
    }

    // LOOP BOMBO
    else { 
        if( arg1 === -1 ){
            if( _enemyBombLive[entityId] !== undefined ){
                _enemyBombLive[entityId]++;
            }
            else {
                _enemyBombLive[entityId] = 1;
            }
            _enemyBombs.push({
                'id': entityId,
                'source': arg2,
                'liveTime': _enemyBombLive[entityId]
            });
        }
        else {
            _enemyBombedFactories.push( arg3 );
        }
    }
}

// DISTANCIA FACTORY
for( var i=0; i < _factoryCount; i++ ){
    var f = _factories[i];
    var avg = 0;
    for( var j=0; j < _myFactories.length; j++ ){
        avg += _distances.get( f.id, _myFactories[j] );
    }
    f.avgDist = avg;
}


var possibleActions = [];

var simulation = {};
var count = 1;
var simFactories = clone( _factories );
while( count <= _maxDistance ){
    for( var i=0; i < _factoryCount; i++ ){
        var f = simFactories[i];

        // ACTUALITZAR INFO ALIATS
        updateIncomings( f.incomings.allies );

        // ACTUALITZAR INFO ENEMICS
        updateIncomings( f.incomings.enemies );



        if( f.owner !== 0 ){
            f.cyborgs += f.production;
        }

        // ME PETE :(
        var incAllies = f.incomings.allies[0] ? f.incomings.allies[0] : 0;
        var incEnemies = f.incomings.enemies[0] ? f.incomings.enemies[0] : 0;

        if( f.owner === 1 ){
            var result = f.cyborgs - ( incEnemies - incAllies );
            if( result < 0 ){
                f.owner = -1;
                f.cyborgs = Math.abs( result );

                // EXECUCOO ACTIONS
                possibleActions.push({
                    'name': 'support ally',
                    'actionFactory': undefined,
                    'targetFactory': f.id,
                    'cyborgs': f.cyborgs,
                    'turnsEffect': count - 1,
                    'score': actionScore( f.production, f.cyborgs, f.avgDist )
                });
            } else {
                f.cyborgs = result;
            }
        }
        else if( f.owner === -1 ){
            var result = f.cyborgs - ( incAllies - incEnemies );
            if( result < 0 ){
                f.owner = 1;
                f.cyborgs = Math.abs( result );
            } else {
                f.cyborgs = result;
                possibleActions.push({
                    'name': 'attack enemy',
                    'actionFactory': undefined,
                    'targetFactory': f.id,
                    'cyborgs': f.cyborgs + f.production + 1,
                    'turnsEffect': count - 1,
                    'score': actionScore( f.production, f.cyborgs + f.production + 1, f.avgDist )
                });
            }
        }
        else {
            var result = f.cyborgs - Math.abs( incAllies - incEnemies );
            if( result < 0 && incAllies > incEnemies ){
                f.owner = 1;
                f.cyborgs = Math.abs( result );
            }
            else if( result < 0 ){
                f.owner = -1;
                f.cyborgs = Math.abs( result );
                possibleActions.push({
                    'name': 'attack enemy',
                    'actionFactory': undefined,
                    'targetFactory': f.id,
                    'cyborgs': f.cyborgs + 1,
                    'turnsEffect': count - 1,
                    'score': actionScore( f.production, f.cyborgs + 1, f.avgDist )
                });
            }
            else {
                f.cyborgs = result;
                possibleActions.push({
                    'name': 'capture neutral',
                    'actionFactory': undefined,
                    'targetFactory': f.id,
                    'cyborgs': f.cyborgs + 1,
                    'turnsEffect': count - 1,
                    'score': actionScore( f.production, f.cyborgs + 1, f.avgDist )
                });
            }
        }
    }
    simulation[count] = clone( simFactories );
    count++;
}

for( var i=0; i < _myFactories.length; i++ ){
    var f = _factories[_myFactories[i]];

    // INCOMING ME PETEN EL CUL
    for( var j=0; j < _enemyBombs.length; j++ ){
        var b = _enemyBombs[j];
        var d = _distances.get( b.source, f.id );
        if( b.liveTime === d ){
            possibleActions.push({
                'name': 'evacuate',
                'actionFactory': f.id,
                'targetFactory': undefined,
                'cyborgs': f.cyborgs,
                'score': actionScore( f.production, 0, 0 )
            });
        }


    }

    // ENVIAR BOMBA
    if( _bombCount > 0 ){
        for( var j=0; j < _enemyFactories.length; j++ ){
            var ef = _factories[_enemyFactories[j]];
            if( _enemyBombedFactories.indexOf( ef.id ) < 0 && ef.production > 0 ){
                possibleActions.push({
                    'name': 'bomb enemy',
                    'actionFactory': undefined,
                    'targetFactory': ef.id,
                    'cyborgs': 0,
                    'score': actionScore( ef.production, 0, ef.avgDist )
                });
            }
        }
    }

    // INCREMENTAR PRODUCCIO
    if( ( _myCyborgs >= _enemyCyborgs + 10 || _myProd < _enemyProd ) 
            && f.production < 3 && f.cyborgs >= 10 ){
        possibleActions.push({
            'name': 'increase production',
            'actionFactory': f.id,
            'cyborgs': 10,
            'score': actionScore( 1, 10, 0 )
        });
    }
}

possibleActions.sort( function(a, b){
    if( a.score !== b.score ){
        return b.score - a.score;
    }
    return a.turns - b.turns;
});

var actions = [];
var actionableFactories = {
    'list': _myFactories.slice(),
    'remove': function( id ){
        var index = this.list.indexOf( id );
        if( index >= 0 ){
            this.list.splice( index, 1 );
        }
    }
}
var handledTargets = [];
while( actionableFactories.list.length > 0 && possibleActions.length > 0 ){
    var a = possibleActions.shift();

    // SWITCH ACTION EXECUCIO
    switch( a.name ){
        case 'attack enemy':
        case 'capture neutral':
        case 'support ally':
            if( handledTargets.indexOf( a.targetFactory ) < 0 ){
                var pActionFactories = actionableFactories.list.slice();
                var iotf = pActionFactories.indexOf( a.targetFactory );
                if( iotf >= 0 ){
                    pActionFactories.splice( iotf, 1 );
                }
                var actionsFactories = findActionFactories( pActionFactories, a.targetFactory, a.turnsEffect, a.cyborgs );
                if( actionsFactories.length > 0 ){
                    for( var i=0; i < actionsFactories.length; i++ ){
                        var af = actionsFactories[i];
                        actions.push( move( af.id, a.targetFactory, af.cyborgs ) );
                        if( af.cyborgs === 0 ){
                            actionableFactories.remove( af.id );
                        }
                    }
                    handledTargets.push( a.targetFactory );
                }
            }
            break;

        // ENVIAR BOMBA ENEMIC
        case 'bomb enemy':
            var actionFactory = findClosestMinCyborgs( actionableFactories.list, a.targetFactory, 0 );
            if( actionFactory >= 0 ){
                actions.push( bomb( actionFactory, a.targetFactory ) );
                actionableFactories.remove( actionFactory );
            }
            break;

        // EVACUAR
        case 'evacuate':
            var myOtherFactories = _myFactories.slice();
            myOtherFactories.splice( myOtherFactories.indexOf( a.actionFactory ), 1 );
            var targetFactory = findClosest( myOtherFactories, a.actionFactory );
            if( targetFactory >= 0 ){
                actions.push( move( a.actionFactory, targetFactory, a.cyborgs ) );
                actionableFactories.remove( a.actionFactory );
            }
            break;

        //INCREMENTAR
        case 'increase production':
            actions.push( increaseProduction( a.actionFactory ) );
            if( _factories[a.actionFactory].cyborgs === 0 ){
                actionableFactories.remove( a.actionFactory );
            }
            break;

        // SPLIT CYBORGS, NO ME FAN FALTA ALLA
        case 'split cyborgs':
            actions.push( move( a.actionFactory, a.targetFactory, a.cyborgs ) );
            if( _factories[a.actionFactory].cyborgs === 0 ){
                actionableFactories.remove( a.actionFactory );
            }
            break;
    }
}

if( actions.length === 0 ){
    actions.push('WAIT');
}
print( actions.join(';') );

}

//PUNTUAR function actionScore( productionGain, cyborgsEngaged, distance ){ var cybDen = cyborgsEngaged > 0 ? cyborgsEngaged : 1; var distDen = distance > 0 ? distance : 1; return productionGain / cybDen / distDen; }

// TROBAR FACTORY NECESARIES PER PEAR function findActionFactories( ids, from, maxDistance, cyborgsNeeded ){ var orderedIds = ids.sort( function(a, b){ var da = _distances.get(a, from); var db = _distances.get(b, from); if( da !== db ){ return da - db; } else { return _factories[b].cyborgs - _factories[a].cyborgs; } });

var found = [];
for( var i=0; i < orderedIds.length; i++ ){
    var d = _distances.get( orderedIds[i], from );
    if( d > maxDistance ){ break; }
    var cybs = Math.min( cyborgsNeeded, _factories[orderedIds[i]].cyborgs );
    if( cybs > 0 ){
        found.push( { 'id': orderedIds[i], 'cyborgs': cybs } );
        cyborgsNeeded -= cybs;
    }
    if( cyborgsNeeded <= 0 ){ break; }
}

return found;

}

// FIND MAX DISTANCE MINIM CYBORGS function findMaxDistanceMinCyborgs( list, from, maxDistance, minCyborgs ){ var orderedList = list.sort( function(a, b){ return _distances.get(b, from) - _distances.get(a, from); } ); for( var i=0; i < orderedList.length; i++ ){ var d = _distances.get( orderedList[i], from ); if( d <= maxDistance && _factories[orderedList[i]].cyborgs >= minCyborgs ){ return orderedList[i]; } } return -1; }

// TROBAR MES PROPER function findClosest( list, from ){ return findClosestMinCyborgs( list, from, 0 ); }

// EL MINIM AL QUE PODEM ATACAR function findClosestMinCyborgs( list, from, minCyborgs ){ var minDist = 100; var closest = -1; for( var i=0; i < list.length; i++ ){ var d = _distances.get( list[i], from ); if( d < minDist && _factories[list[i]].cyborgs >= minCyborgs ){ minDist = d; closest = list[i]; } } return closest; }

// ACTUALITZAR function updateIncomings( object ){ for( var j=0; j < object.max; j++ ){ if( object[j+1] ){ object[j] = object[j+1]; } } object[ object.max ] = undefined; if( object.max > 0 ){ object.max--; } }

// BOMB function bomb( src, dest ){ _bombCount--; return 'BOMB ' + src + ' ' + dest; }

// UP function increaseProduction( fid ){ _factories[fid].cyborgs -= 10; return 'INC ' + fid; }

//MOVE function move( src, dest, cyborgs ){ _factories[src].cyborgs -= cyborgs; return 'MOVE ' + src + ' ' + dest + ' ' + cyborgs; }

//DEP CLONE function clone( obj ){ return JSON.parse(JSON.stringify( obj )); }

// TO STRING DEBUG function stringify( obj ){ return JSON.stringify( obj, null, 2 ); }

Built With

Share this project:

Updates