diff --git a/src/config.js b/src/config.js index 025a42f47..17453a28c 100644 --- a/src/config.js +++ b/src/config.js @@ -65,9 +65,11 @@ global.config = { healMyCreeps: false, repairStructures: false, }, + autoattack: { disabled: false, notify: false, + timeBetweenAttacks: 2000, }, revive: { @@ -79,7 +81,7 @@ global.config = { nextRoom: { boostToControllerLevel: 4, scoutMinControllerLevel: 4, - ttlPerRoomForScout: 500, + ttlPerRoomForScout: 1500, numberOfNextroomers: 10, nextroomerInterval: 500, maxRooms: 20, @@ -128,6 +130,7 @@ global.config = { external: { distance: 3, + defendDistance: 1, }, carry: { diff --git a/src/prototype_creep_fight.js b/src/prototype_creep_fight.js index ec8c649e2..104a0da1e 100644 --- a/src/prototype_creep_fight.js +++ b/src/prototype_creep_fight.js @@ -22,8 +22,8 @@ Creep.prototype.fleeFromHostile = function(hostile) { for (let offset = 0; offset < 8; offset++) { const dir = (direction + offset) % 8 + 1; const pos = this.pos.getAdjacentPosition(dir); - if (pos.lookFor(LOOK_TERRAIN)[0] !== STRUCTURE_WALL && pos.lookFor(LOOK_CREEPS).length === 0) { - direction = direction + offset; + if (!pos.checkForWall() && pos.lookFor(LOOK_CREEPS).length === 0) { + direction = dir; break; } } @@ -169,6 +169,16 @@ Creep.prototype.fightRampart = function(target) { if (range > 3) { return false; } + + const targets = this.pos.findInRange(FIND_HOSTILE_CREEPS, 3, { + filter: this.room.findAttackCreeps, + }); + if (targets.length > 1) { + this.rangedMassAttack(); + } else { + this.rangedAttack(target); + } + const returnCode = this.moveToMy(rampart.pos, 0); if (returnCode === OK) { return true; @@ -179,14 +189,6 @@ Creep.prototype.fightRampart = function(target) { this.log('creep_fight.fightRampart returnCode: ' + returnCode); - const targets = this.pos.findInRange(FIND_HOSTILE_CREEPS, 3, { - filter: this.room.findAttackCreeps, - }); - if (targets.length > 1) { - this.rangedMassAttack(); - } else { - this.rangedAttack(target); - } return true; }; @@ -233,7 +235,8 @@ Creep.prototype.siege = function() { this.memory.hitsLost = this.memory.hitsLast - this.hits; this.memory.hitsLast = this.hits; - if (this.hits - this.memory.hitsLost < this.hits / 2) { + // if (this.hits - this.memory.hitsLost < this.hits / 2) { + if (this.hits < 0.7 * this.hitsMax) { const exitNext = this.pos.findClosestByRange(FIND_EXIT); this.moveTo(exitNext); return true; diff --git a/src/prototype_creep_squad.js b/src/prototype_creep_squad.js new file mode 100644 index 000000000..c2852937f --- /dev/null +++ b/src/prototype_creep_squad.js @@ -0,0 +1,17 @@ +'use strict'; + +Creep.prototype.squadMove = function(squad, maxRange, moveRandom, role) { + if (this.room.name === squad.moveTarget) { + const nextExits = this.room.find(this.memory.routing.route[this.memory.routing.routePos].exit); + const nextExit = nextExits[Math.floor(nextExits.length / 2)]; + const range = this.pos.getRangeTo(nextExit.x, nextExit.y); + if (range < maxRange) { + Memory.squads[this.memory.squad][role][this.id].waiting = true; + if (moveRandom) { + this.moveRandom(); + } + return true; + } + } + return false; +}; diff --git a/src/prototype_room_attack.js b/src/prototype_room_attack.js index 7dc285fe0..48d870006 100644 --- a/src/prototype_room_attack.js +++ b/src/prototype_room_attack.js @@ -1,14 +1,17 @@ 'use strict'; /** - * attack42 is called so because 42 is the only true answer :-) + * Attack42 is called so because 42 is the only true answer :-). * - * USAGE: get a Room Object then .attack42('targetRoomName') - * e.g. Game.rooms[Memory.myRooms[0]].attack42('targetRoomName'); - * TODO add an attack42 event if invader is seen by reserver, sourcer or carry + * USAGE: get a Room Object then `.attack42('targetRoomName')` + * e.g. `Game.rooms[Memory.myRooms[0]].attack42('targetRoomName')`;. + * TODO add an attack42 event if invader is seen by reserver, sourcer or carry. + * + * @example room.attack42('E5S3') + * + * @param {string} roomName - Should be your targetRoomName. + * @param {Array} [spawn] - YourCustomSpawn Array of {creeps: creepsToAdd, role: 'rolesToAdd'}. * - * @param {String} roomName should be your targetRoomName - * @param {Array} [spawn] yourCustomSpawn Array of {creeps: creepsToAdd, role: 'rolesToAdd'} */ Room.prototype.attack42 = function(roomName, spawn) { spawn = spawn || [{ @@ -21,7 +24,6 @@ Room.prototype.attack42 = function(roomName, spawn) { creep: 1, role: 'squadheal', }, - { creep: 2, role: 'autoattackmelee', @@ -35,35 +37,60 @@ Room.prototype.attack42 = function(roomName, spawn) { ]; const closestSpawn = this.closestSpawn(roomName); - // this.log('closestSpawn ' + JSON.stringify(closestSpawn, null, 2)); if (closestSpawn && closestSpawn.id) { - brain.startMeleeSquad(closestSpawn.room, roomName - // , spawn - ); + brain.startMeleeSquad(closestSpawn.room, roomName); } }; -Room.prototype.attackRoom = function() { - function attack0(room) { - room.log('Queuing level 0 attack'); - if (config.autoattack.notify) { - Game.notify(Game.time + ' ' + room.name + ' Queuing autoattacker'); - } +const getClosestRoom = function(roomName) { + const sortByDistance = function(object) { + return Game.map.getRoomLinearDistance(roomName, object); + }; - const sortByDistance = function(object) { - return Game.map.getRoomLinearDistance(room.name, object); - }; + const roomsMy = _.sortBy(Memory.myRooms, sortByDistance); + return Game.rooms[roomsMy[0]]; +}; - const roomsMy = _.sortBy(Memory.myRooms, sortByDistance); +const attacks = { + attack0: function(room) { + const origin = getClosestRoom(room.name); + origin.checkRoleToSpawn('autoattackmelee', 1, undefined, room.name); + return true; + }, - Game.rooms[roomsMy[0]].memory.queue.push({ - role: 'autoattackmelee', - routing: { - targetRoom: room.name, - }, - }); + attack1: function(room) { + const origin = getClosestRoom(room.name); + brain.startSquad(origin.name, room.name); + return true; + }, + attack2: function(room) { + const origin = getClosestRoom(room.name); + origin.attack42(room.name); return true; + }, +}; + +const addRoom = function(player, room) { + if (!player.rooms) { + player.rooms = {}; + } + if (!player.rooms[room.name]) { + player.rooms[room.name] = { + visited: Game.time, + }; + Memory.players[player.name] = player; + } +}; + +const getPlayer = function(name) { + brain.increaseIdiot(name, 0); + return Memory.players[name]; +}; + +Room.prototype.getOwnerName = function() { + if (this.controller.owner) { + return this.controller.owner.username; } if (config.autoattack.disabled) { @@ -75,45 +102,52 @@ Room.prototype.attackRoom = function() { } else { if (this.controller.reservation) { name = this.controller.reservation.username; - } else { - return; } } + return name; +}; + +Room.prototype.launchAutoAttack = function(player) { + if (!player.lastAttacked) { + player.lastAttacked = Game.time; + Memory.players[player.name] = player; + } + if (Game.time < player.lastAttacked + config.autoattack.timeBetweenAttacks) { + return false; + } + this.log(`Queuing level ${player.level} attack`); + if (config.autoattack.notify) { + Game.notify(Game.time + ' ' + this.name + ' Queuing autoattacker'); + } + attacks[`attack${player.level}`](this); + player.counter++; + if (player.counter > 10) { + player.level += 1; + player.counter = 0; + } + Memory.players[player.name] = player; +}; + +Room.prototype.attackRoom = function() { + if (config.autoattack.disabled) { + return true; + } + const name = this.getOwnerName(); + if (!name) { + return; + } // We only exclude players in the friends.js if (friends.indexOf(name) > -1) { return true; } - const getPlayer = function(name) { - brain.increaseIdiot(name, 0); - return Memory.players[name]; - }; - const player = getPlayer(name); - const addRoom = function(player, room) { - if (!player.rooms) { - player.rooms = {}; - } - if (!player.rooms[room.name]) { - player.rooms[room.name] = { - visited: Game.time, - }; - Memory.players[player.name] = player; - } - }; - addRoom(player, this); - if (player.level === 0) { - attack0(this); - player.counter++; - if (player.counter > 5) { - player.level = 1; - player.counter = 0; - } - Memory.players[name] = player; + if (player.level < attacks.length) { + this.launchAutoAttack(player); } return true; }; diff --git a/src/require.js b/src/require.js index 32c33a583..b919f2da6 100644 --- a/src/require.js +++ b/src/require.js @@ -62,3 +62,4 @@ require('role_structurer'); require('role_towerdrainer'); require('role_towerfiller'); require('role_upgrader'); +require('prototype_creep_squad'); diff --git a/src/role_autoattackmelee.js b/src/role_autoattackmelee.js index e1bdea248..1ff3f606c 100644 --- a/src/role_autoattackmelee.js +++ b/src/role_autoattackmelee.js @@ -10,7 +10,7 @@ roles.autoattackmelee = {}; roles.autoattackmelee.settings = { layoutString: 'MA', - amount: [5, 5], + amount: [1, 1], fillTough: true, }; diff --git a/src/role_scout.js b/src/role_scout.js index db8afebd3..b35b833a6 100644 --- a/src/role_scout.js +++ b/src/role_scout.js @@ -23,6 +23,29 @@ function haveNotSeen(creep, room) { creep.memory.skip.indexOf(room) === -1; } +function checkForDefender(creep) { + if (!creep.room.controller) { + return false; + } + if (!creep.room.controller.reservation) { + return false; + } + if (creep.room.controller.reservation.username === Memory.username) { + return false; + } + if (!config.external.defendDistance) { + return false; + } + + const distance = Game.map.getRoomLinearDistance(creep.room.name, creep.memory.base); + if (distance > config.external.defendDistance) { + return false; + } + + creep.log('Spawning defender for external room'); + Game.rooms[creep.memory.base].checkRoleToSpawn('defender', 1, undefined, creep.room.name); +} + roles.scout.execute = function(creep) { if (creep.memory.skip === undefined) { creep.memory.skip = []; @@ -57,6 +80,7 @@ roles.scout.execute = function(creep) { creep.memory.skip.push(creep.memory.search.target); delete creep.memory.scoutSkip; } else { + checkForDefender(creep); creep.memory.search.seen.push(creep.room.name); } if (!setNewTarget(creep)) { diff --git a/src/role_squadheal.js b/src/role_squadheal.js index a6f4ecd62..6e5592f85 100644 --- a/src/role_squadheal.js +++ b/src/role_squadheal.js @@ -10,13 +10,37 @@ roles.squadheal = {}; roles.squadheal.settings = { layoutString: 'MH', - amount: [17, 17], + amount: [1, 1], fillTough: true, }; +roles.squadheal.healClosestCreep = function(creep) { + const myCreep = creep.pos.findClosestByRange(FIND_MY_CREEPS, { + filter: function(object) { + if (object.hits < object.hitsMax) { + return true; + } + return false; + }, + }); + if (myCreep !== null) { + creep.say('heal', true); + const range = creep.pos.getRangeTo(myCreep); + if (range <= 1) { + creep.heal(myCreep); + } else { + creep.moveTo(myCreep); + creep.rangedHeal(myCreep); + } + return true; + } + return false; +}; + roles.squadheal.preMove = function(creep, directions) { + creep.log('preMove'); if (creep.hits < creep.hitsMax) { - console.log('preMove heal'); + creep.log('preMove heal'); creep.heal(creep); creep.memory.routing.reverse = true; if (directions) { @@ -27,23 +51,7 @@ roles.squadheal.preMove = function(creep, directions) { creep.memory.routing.reverse = false; } - const myCreeps = creep.room.find(FIND_MY_CREEPS, { - filter: function(object) { - if (object.hits < object.hitsMax) { - return true; - } - return false; - }, - }); - if (myCreeps.length > 0) { - creep.say('heal', true); - creep.moveTo(myCreeps[0]); - const range = creep.pos.getRangeTo(myCreeps[0]); - if (range <= 1) { - creep.heal(myCreeps[0]); - } else { - creep.rangedHeal(myCreeps[0]); - } + if (roles.squadheal.healClosestCreep(creep)) { return true; } @@ -54,16 +62,8 @@ roles.squadheal.preMove = function(creep, directions) { creep.memory.initialized = true; } if (squad.action === 'move') { - if (creep.room.name === squad.moveTarget) { - const nextExits = creep.room.find(creep.memory.route[creep.memory.routePos].exit); - const nextExit = nextExits[Math.floor(nextExits.length / 2)]; - const range = creep.pos.getRangeTo(nextExit.x, nextExit.y); - if (range < 4) { - Memory.squads[creep.memory.squad].heal[creep.id].waiting = true; - // if (Math.random() > 0.5 * (range - 2)) { - // reverse = true; - // } - } + if (creep.squadMove(squad, 4, false, 'heal')) { + return true; } } } @@ -71,48 +71,40 @@ roles.squadheal.preMove = function(creep, directions) { // TODO need to check if it works roles.squadheal.action = function(creep) { - if (creep.hits < creep.hitsMax) { - creep.log('action heal'); - creep.heal(creep); - creep.say('exit'); - const exit = creep.pos.findClosestByRange(FIND_EXIT); - creep.cancelOrder('move'); - creep.cancelOrder('moveTo'); + creep.heal(creep); - if (creep.pos.x === 0 || creep.pos.y === 0 || creep.pos.x === 49 || creep.pos.y === 49) { - return true; - } - - const search = PathFinder.search( - creep.pos, { - pos: exit, - range: 0, - }, { - roomCallback: creep.room.getCostMatrixCallback(exit), - maxRooms: 1, - } - ); - - if (config.visualizer.enabled && config.visualizer.showPathSearches) { - visualizer.showSearch(search); - } - - if (search.incomplete) { - creep.say('incomplete'); - creep.log(creep.pos.getDirectionTo(exit.x, exit.y)); - const returnCode = creep.move(creep.pos.getDirectionTo(exit.x, exit.y)); - creep.log('rc: ' + returnCode); - return true; + if (creep.room.name !== creep.memory.routing.targetRoom) { + // creep.log('Not in room'); + if (creep.hits < creep.hitsMax) { + creep.moveRandom(); + } else { + // creep.log('delete?'); + delete creep.memory.routing.reached; } - creep.move(creep.pos.getDirectionTo(search.path[0])); - delete creep.memory.routing.reached; return true; + } else { + creep.log('In room'); + // TODO calculate if we would to flip directly back to the previous room + // get all towers and calculate their potential damage + // the damage is applied after the first tick + if (creep.hits < creep.hitsMax) { + creep.log('action heal'); + creep.heal(creep); + creep.say('exit'); + const exit = creep.pos.findClosestByRange(FIND_EXIT); + creep.moveTo(exit); + } else { + creep.log('mrandom'); + creep.moveRandom(); + creep.squadHeal(); + } } - creep.squadHeal(); return true; }; roles.squadheal.execute = function(creep) { - // creep.log('Execute!!!'); + creep.log('Execute!!!'); + creep.heal(creep); + creep.moveRandom(); }; diff --git a/src/role_squadsiege.js b/src/role_squadsiege.js index 85f6a32aa..67752a512 100644 --- a/src/role_squadsiege.js +++ b/src/role_squadsiege.js @@ -14,7 +14,7 @@ roles.squadsiege.settings = { fillTough: true, }; -roles.squadsiege.preMove = function(creep, directions) { +roles.squadsiege.dismantleSurroundingStructures = function(creep, directions) { if (!directions) { return false; } @@ -32,20 +32,22 @@ roles.squadsiege.preMove = function(creep, directions) { creep.say('dismantle'); break; } +}; - if (!creep.memory.initialized) { - Memory.squads[creep.memory.squad].siege[creep.id] = {}; - creep.memory.initialized = true; +roles.squadsiege.preMove = function(creep, directions) { + creep.log('preMove'); + if (!directions) { + return false; } - const squad = Memory.squads[creep.memory.squad]; - if (squad.action === 'move') { - if (creep.room.name === squad.moveTarget) { - const nextExits = creep.room.find(creep.memory.routing.route[creep.memory.routing.routePos].exit); - const nextExit = nextExits[Math.floor(nextExits.length / 2)]; - const range = creep.pos.getRangeTo(nextExit.x, nextExit.y); - if (range < 2) { - Memory.squads[creep.memory.squad].siege[creep.id].waiting = true; - creep.moveRandom(); + roles.squadsiege.dismantleSurroundingStructures(creep, directions); + if (creep.memory.squad) { + if (!creep.memory.initialized) { + Memory.squads[creep.memory.squad].siege[creep.id] = {}; + creep.memory.initialized = true; + } + const squad = Memory.squads[creep.memory.squad]; + if (squad.action === 'move') { + if (creep.squadMove(squad, 2, true, 'siege')) { return true; } } @@ -55,6 +57,14 @@ roles.squadsiege.preMove = function(creep, directions) { // TODO need to check if it works roles.squadsiege.action = function(creep) { + creep.say('action'); + if (creep.room.name !== creep.memory.routing.targetRoom) { + if (creep.hits < creep.hitsMax) { + creep.moveRandom(); + } else { + delete creep.memory.routing.reached; + } + } creep.siege(); };