diff --git a/spec/engine/game/roomsSpec.js b/spec/engine/game/roomsSpec.js index 866d552b..749d77ed 100644 --- a/spec/engine/game/roomsSpec.js +++ b/spec/engine/game/roomsSpec.js @@ -6,18 +6,25 @@ const _ =require('lodash'), describe('rooms', () => { describe('RoomPosition', () => { - let globals = {}; + let globals; beforeEach(()=>{ + globals = {} const runtimeData = { staticTerrainData: require('../../helpers/mocks/rooms').terrain }; const register = { - wrapFn: function(fn) { return fn } + wrapFn: function(fn) { return fn }, + rooms: { E2S7: {} }, + _useNewPathFinder: true, }; rooms.make(runtimeData, {}, register, globals); rooms.makePos(register); + + for (var i in runtimeData.rooms) { + register.rooms[i] = new globals.Room(i); + } }); it('Exists',()=>{ @@ -54,5 +61,86 @@ describe('rooms', () => { expect(pos.y).toBe(15); expect(pos.roomName).toBe('E2S7'); }); + + describe("findClosestByPath", () => { + const newPos = ({x}) => new globals.RoomPosition(x, 0, "E2S7"); + + /** + * In context of `RoomPosition.findClosestByPath` `path` only has to include the last position. + */ + const mockPathFinderSearch = (path) => { + globals.PathFinder = { + search: () => ({ + // Only the last position of a path is considered in search + path, + }) + } + } + + it("Finds target according to PathFinder", () => { + const pos = newPos({ x: 0 }); + const closeTarget = newPos({ x: 5 }); + const farTarget = newPos({ x: 10 }); + + mockPathFinderSearch([closeTarget]) + + const result = pos.findClosestByPath([ + closeTarget, + farTarget, + ]); + + expect(result).toEqual(closeTarget); + }); + + it("Finds target with range option", () => { + const range = 2; + const targetX = 5; + + const pos = newPos({ x: 0 }); + const target = newPos({ x: targetX }); + const pathEnd = newPos({ x: targetX - range }); + + mockPathFinderSearch([pathEnd]) + const searchSpy = spyOn(globals.PathFinder, 'search').and.callThrough() + + const result = pos.findClosestByPath([target], { range }); + + expect(result).toEqual(target); + expect(searchSpy.calls.count()).toBe(1) + expect(searchSpy.calls.argsFor(0)[0]).toEqual(pos) + expect(searchSpy.calls.argsFor(0)[1].length).toBe(1) + expect(searchSpy.calls.argsFor(0)[1]).toContain({ range, pos: target }) + }) + + it("Fails to find target out of range", () => { + const range = 2; + const targetX = 5; + + const pos = newPos({ x: 0 }); + const target = newPos({ x: targetX }); + const pathEnd = newPos({ x: targetX - range - 1 }); + + mockPathFinderSearch([pathEnd]) + + const result = pos.findClosestByPath([target], { range }); + + expect(result).toEqual(null); + }) + + it("Picks first target in range of the path even if it's further away", () => { + const range = 2; + + const pos = newPos({ x: 0 }); + const targetOut = newPos({ x: 3 }); + const targetFar = newPos({ x: 2 }); + const targetNear = newPos({ x: 1 }); + + mockPathFinderSearch([]) + + const result = pos.findClosestByPath([targetOut, targetFar, targetNear], { range }); + + expect(result).toEqual(targetFar); + }) + }); }); }); \ No newline at end of file diff --git a/src/game/rooms.js b/src/game/rooms.js index f2bac2e1..d7cd3db6 100644 --- a/src/game/rooms.js +++ b/src/game/rooms.js @@ -305,6 +305,8 @@ function _findClosestByPath2(fromPos, objects, opts) { opts = opts || {}; + const range = opts.range === undefined ? 1 : opts.range; + if(_.isNumber(objects)) { objects = register.rooms[fromPos.roomName].find(objects, {filter: opts.filter}); } @@ -325,7 +327,7 @@ function _findClosestByPath2(fromPos, objects, opts) { if(i.pos) { i = i.pos; } - return {range: 1, pos: i}; + return {range, pos: i}; }); if(opts.avoid) { @@ -365,7 +367,7 @@ function _findClosestByPath2(fromPos, objects, opts) { } objects.forEach(obj => { - if(lastPos.isNearTo(obj)) { + if(lastPos.inRangeTo(obj, range)) { result = obj; } });