UNPKG

@screeps/engine

Version:

This is a module for Screeps standalone server. See [main repository](https://github.com/screeps/screeps) for more info.

435 lines (355 loc) 16.5 kB
const _ =require('lodash'), utils = require('../../../../src/utils'), driver = utils.getDriver(), C = driver.constants, movement = require('../../../../src/processor/intents/movement'), roomsEnv = require('../../../helpers/mocks/rooms'), creepsEnv = require('../../../helpers/mocks/creeps'), powerCreepsEnv = require('../../../helpers/mocks/powerCreeps'), intents = require('../../../helpers/mocks/intents'); describe('movement', ()=>{ let scope; beforeEach(()=>{ scope = intents.scope; intents.reset(); }); describe('One creep', ()=>{ let noMove, damaged; beforeEach(()=>{ noMove = creepsEnv.createCreep('noMove', {x: 24, y: 24}); damaged = creepsEnv.createCreep('fullSpeed', {x: 23, y: 28}); _.forEach(damaged.body, i => {if(i.type == C.MOVE) i.hits = 0}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it('does not move without MOVE parts',()=>{ noMove.move(7); movement.check(false); intents.ticks(); expect(noMove.x).toBe(24); expect(noMove.y).toBe(24); }); it('does not move with all MOVE parts dead',()=>{ damaged.move(1); movement.check(false); intents.ticks(); expect(damaged.x).toBe(23); expect(damaged.y).toBe(28); }); it('blocks his tile when can not move',()=>{ const fullSpeed = creepsEnv.createCreep('fullSpeed', {x: 22, y: 27}); damaged.move(1); fullSpeed.move(4); movement.check(false); intents.ticks(); expect(damaged.x).toBe(23); expect(damaged.y).toBe(28); expect(fullSpeed.x).toBe(22); expect(fullSpeed.y).toBe(27); }); describe('Offroad creep', ()=>{ let scout, scout2; beforeEach(()=>{ scout = creepsEnv.createCreep('scout', {x: 24, y: 24}); scout2 = creepsEnv.createCreep('scout', {x: 24, y: 25}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it("moves over plain",()=>{ scout.move(7); movement.check(false); intents.ticks(); expect(scout.x).toBe(23); expect(scout.y).toBe(24); expect(scout.fatigue).toBe(0); }); it("does not move into wall",()=>{ scout.move(4); movement.check(false); intents.ticks(); expect(scout.x).toBe(24); expect(scout.y).toBe(24); expect(scout.fatigue).toBe(0); }); it("does not move into another creep",()=>{ scout.move(5); movement.check(false); intents.ticks(); expect(scout.x).toBe(24); expect(scout.y).toBe(24); expect(scout.fatigue).toBe(0); expect(scout2.x).toBe(24); expect(scout2.y).toBe(25); expect(scout2.fatigue).toBe(0); }); }); describe('Full speed creep',()=>{ let creep; beforeEach(()=>{ creep = creepsEnv.createCreep('fullSpeed', {x: 24, y: 24}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it("does not move when tired",()=>{ creep.fatigue = 1; creep.move(2); movement.check(false); intents.ticks(); expect(creep.x).toBe(24); expect(creep.y).toBe(24); expect(creep.fatigue).toBe(0); // rested this tick }); it("is not tired after moving over plain tile",()=>{ creep.move(2); movement.check(false); intents.ticks(); expect(creep.x).toBe(25); expect(creep.y).toBe(23); expect(creep.fatigue).toBe(0); }); it("is tired after moving over swamp tile ",()=>{ creep.move(3); movement.check(false); intents.ticks(); expect(creep.x).toBe(25); expect(creep.y).toBe(24); expect(creep.fatigue).toBe(8); }); }); describe('Half speed creep',()=>{ let creep; beforeEach(()=>{ creep = creepsEnv.createCreep('halfSpeed', {x: 24, y: 24}); movement.init([creep,{type: 'road', x: 23, y: 24}], roomsEnv.terrain.E2S7); }); it("is tired after moving over plain tile",()=>{ creep.move(2); movement.check(false); intents.ticks(); expect(creep.x).toBe(25); expect(creep.y).toBe(23); expect(creep.fatigue).toBe(2); }); it("is tired after moving over swamp tile",()=>{ creep.move(3); movement.check(false); intents.ticks(); expect(creep.x).toBe(25); expect(creep.y).toBe(24); expect(creep.fatigue).toBe(18); }); it("is not tired after moving over road",()=>{ creep.move(7); movement.check(false); intents.ticks(); expect(creep.x).toBe(23); expect(creep.y).toBe(24); expect(creep.fatigue).toBe(0); }); }); }); describe('Two creeps', ()=>{ let scout1, scout2; beforeEach(()=>{ scout1 = creepsEnv.createCreep('scout', {x: 24, y: 24}); scout2 = creepsEnv.createCreep('scout', {x: 24, y: 25}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it("should follow step-to-step",()=>{ scout1.move(5); scout2.move(5); movement.check(false); intents.ticks(); expect(scout1.x).toBe(24); expect(scout1.y).toBe(25); expect(scout2.x).toBe(24); expect(scout2.y).toBe(26); }); it("should swap positions",()=>{ scout1.move(5); scout2.move(1); movement.check(false); intents.ticks(); expect(scout1.x).toBe(24); expect(scout1.y).toBe(25); expect(scout2.x).toBe(24); expect(scout2.y).toBe(24); }); }); describe('Single Power Creep',()=>{ let operator; beforeEach(()=>{ operator = powerCreepsEnv.createPowerCreep('FullOperator', {x: 21, y: 26}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it('blocks his tile when do not move',()=>{ const fullSpeed = creepsEnv.createCreep('fullSpeed', {x: 22, y: 27}); fullSpeed.move(8); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(22); expect(fullSpeed.y).toBe(27); }); it('swaps position with a regular creep',()=>{ const fullSpeed = creepsEnv.createCreep('fullSpeed', {x: 22, y: 27}); operator.move(4); fullSpeed.move(8); movement.check(false); intents.ticks(); expect(operator.x).toBe(22); expect(operator.y).toBe(27); expect(fullSpeed.x).toBe(21); expect(fullSpeed.y).toBe(26); }); }); describe('When several creeps trying to move onto the same tile',()=>{ let fullSpeed1, fullSpeed2, halfSpeed1, halfSpeed2; beforeEach(()=>{ fullSpeed1 = creepsEnv.createCreep('fullSpeed', {x: 24, y: 24}); fullSpeed2 = creepsEnv.createCreep('fullSpeed', {x: 23, y: 26}); halfSpeed1 = creepsEnv.createCreep('halfSpeed', {x: 24, y: 25}); halfSpeed2 = creepsEnv.createCreep('halfSpeed', {x: 24, y: 26}); movement.init([fullSpeed1, halfSpeed1, halfSpeed2], roomsEnv.terrain.E2S7); }); it('creep with best moves/weight ratio takes priority',()=>{ fullSpeed1.move(6); halfSpeed1.move(7); movement.check(false); intents.ticks(); expect(fullSpeed1.x).toBe(23); expect(fullSpeed1.y).toBe(25); expect(halfSpeed1.x).toBe(24); expect(halfSpeed1.y).toBe(25); }); it('creep having follower takes priority',()=>{ fullSpeed1.move(6); halfSpeed1.move(7); halfSpeed2.move(1); movement.check(false); intents.ticks(); expect(fullSpeed1.x).toBe(24); expect(fullSpeed1.y).toBe(24); expect(halfSpeed1.x).toBe(23); expect(halfSpeed1.y).toBe(25); }); it('creep that pulls someone takes priority',()=>{ halfSpeed1.move(7); halfSpeed1.pull(fullSpeed1._id); fullSpeed1.move(halfSpeed1._id); fullSpeed2.move(1); halfSpeed2.move(7); movement.check(false); intents.ticks(); expect(fullSpeed2.x).toBe(23); expect(fullSpeed2.y).toBe(26); expect(halfSpeed1.x).toBe(23); expect(halfSpeed1.y).toBe(25); }); it('creep that being pulled takes priority',()=>{ halfSpeed1.move(7); halfSpeed1.pull(halfSpeed2._id); halfSpeed2.move(halfSpeed1._id); fullSpeed1.move(5); movement.check(false); intents.ticks(); expect(halfSpeed2.x).toBe(24); expect(halfSpeed2.y).toBe(25); expect(fullSpeed1.x).toBe(24); expect(fullSpeed1.y).toBe(24); }); }); describe('Creep pulling another creep',()=>{ let fullSpeed, halfSpeed, halfSpeed2, noMove; beforeEach(()=>{ noMove = creepsEnv.createCreep('noMove', {x: 23, y: 25}); halfSpeed = creepsEnv.createCreep('halfSpeed', {x: 24, y: 24}); halfSpeed2 = creepsEnv.createCreep('halfSpeed', {x: 25, y: 23}); fullSpeed = creepsEnv.createCreep('fullSpeed', {x: 24, y: 25}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it("receives another creep's fatigue if he follows (direction syntax)",()=>{ fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(5); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed.fatigue).toBe(0); expect(fullSpeed.fatigue).toBe(2); // he carries 1 his own TOUGH plus 2 TOUGH of halfSpeed using 1 his MOVE part plus 1 MOVE part of halfSpeed }); it("receives another creep's fatigue if he follows (creep syntax)",()=>{ fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(fullSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed.fatigue).toBe(0); expect(fullSpeed.fatigue).toBe(2); // he carries 1 his own tough plus 2 tough of halfSpeed using 1 his MOVE part plus 1 MOVE part of halfSpeed }); it("does not receive another creep's fatigue if he does not follow",()=>{ fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(8); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(23); expect(halfSpeed.y).toBe(23); expect(halfSpeed.fatigue).toBe(2); expect(fullSpeed.fatigue).toBe(0); }); it("moves a creep without MOVE parts",()=>{ fullSpeed.move(8); fullSpeed.pull(noMove._id); noMove.move(fullSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(23); expect(fullSpeed.y).toBe(24); expect(noMove.x).toBe(24); expect(noMove.y).toBe(25); expect(noMove.fatigue).toBe(0); expect(fullSpeed.fatigue).toBeGreaterThan(0); }); it("moves a creep with fatigue",()=>{ halfSpeed.fatigue = 2; halfSpeed.move(fullSpeed._id); fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed.fatigue).toBe(0); expect(fullSpeed.fatigue).toBe(4); // TOUGH parts: 3, MOVE parts: 1 (halfspeed's MOVE can't be used because of fatigue) }); it("prevents circular/sequental pulls (2 creeps)",()=>{ halfSpeed.move(2); halfSpeed.pull(halfSpeed2._id); halfSpeed2.move(6); halfSpeed2.pull(halfSpeed._id); movement.check(false); intents.ticks(); expect(halfSpeed.x).toBe(25); expect(halfSpeed.y).toBe(23); expect(halfSpeed2.x).toBe(24); expect(halfSpeed2.y).toBe(24); // in this case, one and only one pull should succeeded, either of them, so expectations changed to: expect(halfSpeed.fatigue*halfSpeed2.fatigue).toBe(0); // at least one of fatigues should be 0 expect(halfSpeed.fatigue+halfSpeed2.fatigue).toBeGreaterThan(0); // and the other shouldn't be 0 }); }); describe('Creep pulling chain of creeps',()=>{ beforeEach(()=>{ halfSpeed = creepsEnv.createCreep('halfSpeed', {x: 24, y: 24}); halfSpeed2 = creepsEnv.createCreep('halfSpeed', {x: 25, y: 23}); noMove = creepsEnv.createCreep('noMove', {x: 23, y: 25}); fullSpeed = creepsEnv.createCreep('fullSpeed', {x: 24, y: 25}); movement.init(scope.roomObjects, roomsEnv.terrain.E2S7); }); it('receives fatigue for all of them',()=>{ fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(fullSpeed._id); halfSpeed.pull(halfSpeed2._id); halfSpeed2.move(halfSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed2.x).toBe(24); expect(halfSpeed2.y).toBe(24); expect(fullSpeed.fatigue).toBe(4); // total TOUGH parts: 5, total MOVE parts: 3 expect(halfSpeed.fatigue).toBe(0); expect(halfSpeed2.fatigue).toBe(0); }); it('receives MOVE parts contribution of all pulled creeps', ()=>{ fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(fullSpeed._id); halfSpeed.pull(halfSpeed2._id); halfSpeed2.move(halfSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed2.x).toBe(24); expect(halfSpeed2.y).toBe(24); expect(fullSpeed.fatigue).toBe(4); // total TOUGH parts: 5, total MOVE parts: 1 (pulled moves can't be used) expect(halfSpeed.fatigue).toBe(0); expect(halfSpeed2.fatigue).toBe(0); }); it('receives MOVE parts contribution of all pulled creeps except fatigued', ()=>{ halfSpeed.fatigue = 2; halfSpeed2.fatigue = 2; fullSpeed.move(5); fullSpeed.pull(halfSpeed._id); halfSpeed.move(fullSpeed._id); halfSpeed.pull(halfSpeed2._id); halfSpeed2.move(halfSpeed._id); movement.check(false); intents.ticks(); expect(fullSpeed.x).toBe(24); expect(fullSpeed.y).toBe(26); expect(halfSpeed.x).toBe(24); expect(halfSpeed.y).toBe(25); expect(halfSpeed2.x).toBe(24); expect(halfSpeed2.y).toBe(24); expect(fullSpeed.fatigue).toBe(8); // total TOUGH parts: 5, total MOVE parts: 1 (pulled moves can't be used) expect(halfSpeed.fatigue).toBe(0); expect(halfSpeed2.fatigue).toBe(0); }); }); });