diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..326517b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Upload Script", + "type": "shell", + "command": "node", + "args": [ + "d:/code/screeps/main.js" + ], + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/builder.js b/builder.js index 53a438b..d14d4f4 100644 --- a/builder.js +++ b/builder.js @@ -1,13 +1,15 @@ +const utils=require('utils') module.exports = { run(creep) { - if (creep.carry.energy < creep.carryCapacity){ - if(ERR_NOT_IN_RANGE==creep.withdraw(Game.spawns.Spawn1,RESOURCE_ENERGY)){ - creep.moveTo(Game.spawns.Spawn1); - } - }else{ - let construction_site=creep.room.find(FIND_CONSTRUCTION_SITES); - if(ERR_NOT_IN_RANGE==creep.build(construction_site[0])){ - creep.moveTo(construction_site[0]); + if (creep.working_target_id) { + let working_target_id = creep.working_target_id; + let working_target = Game.getObjectById(working_target_id); + if(utils.distance(creep.pos,working_target.pos)>1.5){ + creep.moveTo(working_target); + }else{ + creep.pickup(RESOURCE_ENERGY); + //TODO:需要适应不同的建筑 + creep.upgradeController(working_target); } } } diff --git a/harvester.js b/harvester.js index 933faf4..3a7cf42 100644 --- a/harvester.js +++ b/harvester.js @@ -1,14 +1,18 @@ +const path=require('path') module.exports = { run(creep) { //分配source if (creep.carry.energy < creep.carryCapacity) { let sources = creep.room.find(FIND_SOURCES); + //TODO:只去一个地方 if (creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(sources[0]); + path.visualPath(creep.pos,sources[0].pos); } } else { if (creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) { creep.moveTo(Game.spawns['Spawn1']); + path.visualPath(creep.pos,Game.spawns['Spawn1'].pos); } } } diff --git a/init.js b/init.js index 515b0e5..3e81f72 100644 --- a/init.js +++ b/init.js @@ -2,10 +2,22 @@ module.exports = { init() { - if (!Memory.Source) { - Memory.Source = new Object(); - Memory.Source.Energy = []; - } + // if (!Memory.Source) { + // Memory.Source = new Object(); + // Memory.Source.Energy = []; + // } + // if (!Memory.Controller) { + // Memory.Controller = []; + // } + if (!Memory.Task) { + Memory.Task = {} + }; + Memory.Task.HighPorioty = []; + Memory.Task.LowPorioty = []; + //WorkingTarget是被跟踪物,可以是一个structure、energy、constructionSite,也可以是一个creep + if (!Memory.WorkingTarget) { + Memory.WorkingTarget = [] + }; } } diff --git a/main.js b/main.js index a1428e0..19e71a9 100644 --- a/main.js +++ b/main.js @@ -1,21 +1,36 @@ const init = require('init') -const harvester = require('harvester'); -const picker = require('picker'); const util = require('utils'); -const transfer = require('transfer'); +const mount = require('mount') module.exports.loop = function () { + //clean creeps + cleanCreeps() init.init(); - // if (Game.time % 20 == 0) { - assign_creep_to_enery_source();//由于循环较多,每20 tick执行一次 - // } - - Creep.prototype.action = action; - if ((_(Game.creeps).filter({ memory: { role: 'harvester' } }).size() + _(Game.creeps).filter({ memory: { role: 'picker' } }).size()) < 2) { - createHarvestCreep(); - } else { - if (_(Game.creeps).filter({ memory: { role: 'transfer' } }).size() < 2) { + mount.mount() + assign_harvester_picker_to_enery_source(); + assign_transfer_to_picker() + assign_builder_to_controller(); + // assign_controller(); + let isSpawning = false + let energy_source_number = _.filter(Game.spawns['Spawn1'].room.find(FIND_SOURCES_ACTIVE)).length; + let harvester_number = _(Game.creeps).filter({ memory: { role: 'harvester' } }).size(); + let picker_number = _(Game.creeps).filter({ memory: { role: 'picker' } }).size(); + if (!Game.spawns['Spawn1'].spawning) { + if ((harvester_number + picker_number) < energy_source_number) { + isSpawning = true + createHarvestCreep(); + } + if (_(Game.creeps).filter({ memory: { role: 'transfer' } }).size() < 2 && !isSpawning) { + createTransferCreep(); + } + let builder_number = _.filter(Game.creeps, { memory: { role: 'builder' } }).length + //创造一个builder升级room controller + if (Game.spawns['Spawn1'].room.controller && builder_number == 0 && !isSpawning) { + createBuilderCreep(); + } + //判断是否需要再增加1个transfer + let transfer_number = _.filter(Game.creeps, { memory: { role: 'transfer' } }).length + if ((builder_number + harvester_number + picker_number) > transfer_number && !isSpawning) { createTransferCreep(); - } } chanage_role(); @@ -23,22 +38,40 @@ module.exports.loop = function () { } -function action() { - let role = this.memory.role; - // this.say(`${role}`); - switch (role) { - case "harvester": - harvester.run(this) - break; - case "picker": - picker.run(this) - break; - case "transfer": - transfer.run(this) - break; + +function cleanCreeps() { + for (let i in Memory.creeps) { + if (!Game.creeps[i]) { + delete Memory.creeps[i]; + } } } + +function assign_transfer_to_picker() { + //判断有多少个picker的transfer为0 + let all_picker = _.filter(Game.creeps, { memory: { role: 'picker' } }) + let picker_has_no_creep = _.filter(all_picker, function (picker) { + return !_.find(Memory.WorkingTarget, target => target.id == picker.id)//Memory.WorkingTarget中没有这个picker目标 + }) + _.each(picker_has_no_creep, function (picker) { + Memory.WorkingTarget.push({ id: picker.id, working_creep_names: [], cate: 'picker' })//在Memory.WorkingTarget加入需要creep的Picker + }) + let picker_memories = _.filter(Memory.WorkingTarget, picker_memory => picker_memory.working_creep_names.length == 0) + if (picker_memories.length > 0) { + let available_transfer = _.filter(Game.creeps, creep => !creep.working_target_id && (creep.memory.role == 'transfer')) + if (available_transfer.length > 0) {//一次只安排一个creep + let opt = { + memory: picker_memories, + creep_name_to_assgin_array: [available_transfer[0].name] + } + assign_creeps(opt) + } + } + + +} + function assign_task() { for (const creep_id in Game.creeps) { let creep = Game.creeps[creep_id]; @@ -47,67 +80,123 @@ function assign_task() { } -function assign_creep_to_enery_source() { - //清理Energy中已经没有的Source - if (Memory.Source.Energy) { - _(Memory.Source.Energy).remove(function (r) { return Game.getObjectById(r['id']) === undefined; }); +function assign_controller() { + let builder_creep_array = _.filter(Game.creeps, { memory: { role: 'builder' } }) + if (builder_creep_array.length == 0) { + return; } - let sources = Game.spawns['Spawn1'].room.find(FIND_SOURCES); - for (let source of sources) { - let id = source.id - if (_(Memory.Source.Energy).findIndex(f => f['id'] == id) == -1) { - Memory.Source.Energy.push({ 'id': id, 'working_creep_names': [] }); - } + let builder_creep = builder_creep_array[0] + //TODO: 不能用0来判断,否则经常不会进入判断 + if (Game.spawns['Spawn1'].room.controller && Memory.WorkingTarget && Memory.WorkingTarget.Creep && Memory.WorkingTarget.Creep.length == 0) { + Memory.WorkingTarget.Creep.push({ 'id': builder_creep.id, 'working_creep_names': [] }) } - let harvester_creeps = _(Game.creeps).filter(function (r) { return r.memory.role == 'harvester' | r.memory.role == 'picker'; }).value(); - // 从Memory.Source.Energy中移除已经没有的creep - for (let mem_source of Memory.Source.Energy) { - _(mem_source['working_creep_names']).each(function (creep_name) { - if (Game.creeps[creep_name] === undefined) { - console.log(`deleted ${creep_name}`); - return true; - } - return false; - }) - _(mem_source['working_creep_names']).remove(creep_name => Game.creeps[creep_name] === undefined) - // let new_working_creeep_name_array=[]; - // new_working_creeep_name_array.push(...mem_source['working_creep_names']) - // for(let creep_name of mem_source['working_creep_names']){ - // if(Game.creeps[creep_name]===undefined){ - // delete new_working_creeep_name_array[creep_name] - // console.log(`deleted ${creep_name}`); - // } - // } - // new_working_creeep_name_array=_(new_working_creeep_name_array).filter(r=>r!=undefined).value(); - // mem_source['working_creep_names'].splice(0,mem_source['working_creep_names'].length); - // mem_source['working_creep_names'].push(...new_working_creeep_name_array); - // console.log(`Now it's ${mem_source['working_creep_names']}`); + if (Memory.WorkingTarget.Creep.length > 0) { + let opt = {} + opt.creep_name_to_assgin_array = [builder_creep.name] + opt.memory = Memory.WorkingTarget.Creep + assign_creeps(opt) } - let unassigned_creeps_names = []; - for (let creep of harvester_creeps) {//统计哪些没有工作 - // let assigned = false; - if (creep.working_target_id === undefined) { - unassigned_creeps_names.push(creep.name); - } - } - //开始安排 - for (let unassigned_creep_name of unassigned_creeps_names) { - //能源矿已有creep的数量 - let energy_working_creep_n = []; - for (let mem_source of Memory.Source.Energy) { - energy_working_creep_n.push(mem_source['working_creep_names'].length); - } - let energy_index = _(energy_working_creep_n).indexOf(_(energy_working_creep_n).min()); - Memory.Source.Energy[energy_index]['working_creep_names'].push(unassigned_creep_name); - Game.creeps[unassigned_creep_name].working_target_id = Memory.Source.Energy[energy_index]['id']; - } - - - } +function removeUnusedMemoryItem(memory) { + //清理Memory中已经不存在的工作对象 + let available_working_target_id_array = [];//还存在的target + _.remove(memory, function (r) { + if (Game.getObjectById(r.id) === undefined || Game.getObjectById(r.id) === null) + return true + else { + available_working_target_id_array.push(r.id) + } + }) + return memory +} + +function assign_creeps(opt) { + let memory = opt.memory + let creep_name_to_assgin_array = opt.creep_name_to_assgin_array//需要分配工作的creeps + //清理Memory中已经不存在的工作对象 + removeUnusedMemoryItem(memory) + //清理Memroy中已经不存在的creep + _.each(memory, function (m) { + _.remove(m.working_creep_names, name => Game.creeps[name] === undefined || Game.creeps[name] === null) + }) + _.each(creep_name_to_assgin_array, function (creep_name) { + //先计算每一个target目前有多少个creeps了 + let working_creeps_of_target_array = [] + _.each(memory, m => working_creeps_of_target_array.push(m.working_creep_names.length)) + let target_to_add_creep = _.filter(memory, m => m.working_creep_names.length == _.min(working_creeps_of_target_array))//选择目前已有creep最少的,对其添加creep + if (target_to_add_creep.length > 0) { + target_to_add_creep[0].working_creep_names.push(creep_name)//target记录自己安排的creep + Game.creeps[creep_name].working_target_id = target_to_add_creep[0].id//将target安排给creep + } + }) + + +} + +function assign_harvester_picker_to_enery_source() { + let sources = Game.spawns['Spawn1'].room.find(FIND_SOURCES_ACTIVE); + let all_memory = Memory.WorkingTarget + for (let source of sources) { + let id = source.id + if (_(all_memory).findIndex(f => f['id'] == id) == -1) { + all_memory.push({ 'id': id, 'working_creep_names': [], "cate": 'ENERGY_SOURCE' }); + } + }//向Memory.WorkingTarget里添加所有的Energy Source + removeUnusedMemoryItem(all_memory)//移除已经不存在的target + //寻找Energy Source的Memory + let energy_memory = _.filter(all_memory, { cate: 'ENERGY_SOURCE' }) + //检查一下是否每一个energy至少有一个creep + //先移除已经失效的creep + _.each(energy_memory, function (m) { + _.remove(m.working_creep_names, creep_name => !Game.creeps[creep_name])//如果一个creep已经不存在了,就从列表中移除 + }) + //寻找creep为0的energy source + let energy_source_need_creep_array = _.filter(energy_memory, m => m.working_creep_names.length == 0) + if (energy_source_need_creep_array.length > 0) { + //找到一个空闲的creep + let available_creep_array = _.filter(Game.creeps, creep => !creep.working_target_id && (creep.memory.role == 'harvester' || creep.memory.role == 'picker')) + if (available_creep_array.length > 0) {//每次只安排一个 + let opt = { + memory: energy_memory, + creep_name_to_assgin_array: [available_creep_array[0].name] + } + assign_creeps(opt) + } + } + + +} + +function assign_builder_to_controller() { + //判断room controller 是否有creep,没有则添加 + if (!_.find(Memory.WorkingTarget, target => target.id == Game.spawns['Spawn1'].room.controller.id)) { + Memory.WorkingTarget.push({ id: Game.spawns['Spawn1'].room.controller.id, working_creep_names: [], cate: 'ROOM_CONTROLLER' }) + } + let room_controller_mem = _.filter(Memory.WorkingTarget, { cate: 'ROOM_CONTROLLER' }) + //先移除已经失效的creep + _.each(room_controller_mem, function (m) { + _.remove(m.working_creep_names, creep_name => !Game.creeps[creep_name])//如果一个creep已经不存在了,就从列表中移除 + }) + //寻找creep为0的room controller + let room_controller_need_creep_array = _.filter(room_controller_mem, m => m.working_creep_names.length == 0) + if (room_controller_need_creep_array.length > 0) { + let builder_creep = _.filter(Game.creeps, creep => !creep.working_target_id || creep.memory.role == 'builder') + if (builder_creep.length > 0) { + + let opt = { + memory: room_controller_mem, + creep_name_to_assgin_array: [builder_creep[0].name] + } + assign_creeps(opt) + } + } +} + + + function chanage_role() { if (_(Game.creeps).filter({ memory: { role: 'transfer' } }).size() > 0) { let harvester_array = _(Game.creeps).filter({ memory: { role: 'harvester' } }).value(); @@ -124,21 +213,6 @@ function chanage_role() { } } -function get_creep_with_name(inlcude_string) { - let creeps = []; - for (const creep_id in Game.creeps) { - let creep = Game.creeps[creep_id]; - if (creep.name.include(inlcude_string)) { - creeps.push(creep); - } - } - return creeps; -} - -function count(hash_container) { - return Object.keys(hash_container).length -} - function createHarvestCreep() { //create new creep let new_creep_name = "AUTO_CREATE_Harvester_" + util.uuid(); @@ -148,7 +222,7 @@ function createHarvestCreep() { Game.creeps[new_creep_name].memory.role = 'harvester'; console.log('Create new creep name ' + new_creep_name); } else { - console.log(`failed to create harvester with code ${Re_code}`); + // console.log(`failed to create harvester with code ${Re_code}`); } } @@ -161,6 +235,19 @@ function createTransferCreep() { Game.creeps[new_creep_name].memory.role = 'transfer'; console.log('Create new creep name ' + new_creep_name); } else { - console.log(`failed to create transfer with code ${Re_code}`); + // console.log(`failed to create transfer with code ${Re_code}`); } } + +function createBuilderCreep() { + //create new creep + let new_creep_name = "AUTO_CREATE_Builder_" + util.uuid(); + let Re_code; + Re_code = Game.spawns['Spawn1'].createCreep([MOVE, WORK, WORK], new_creep_name) + if (Re_code == new_creep_name) { + Game.creeps[new_creep_name].memory.role = 'builder'; + console.log('Create new creep name ' + new_creep_name); + } else { + // console.log(`failed to create builder with code ${Re_code}`); + } +} \ No newline at end of file diff --git a/mount.js b/mount.js new file mode 100644 index 0000000..6e31788 --- /dev/null +++ b/mount.js @@ -0,0 +1,40 @@ +const harvester = require('harvester'); +const picker = require('picker'); +const transfer = require('transfer'); +const builder = require('builder'); +module.exports = { + mount() { + Creep.prototype.action = action; + if (!(Creep.prototype.hasOwnProperty('working_target_id'))) { + Object.defineProperty(Creep.prototype, 'working_target_id', { + get: function () { + return this.memory.working_target_id + }, + set: function (id) { + this.memory.working_target_id = id + } + } + ) + } + } +} + + +function action() { + let role = this.memory.role; + // this.say(`${role}`); + switch (role) { + case "harvester": + harvester.run(this) + break; + case "picker": + picker.run(this) + break; + case "transfer": + transfer.run(this) + break; + case "builder": + builder.run(this) + break; + } +} \ No newline at end of file diff --git a/path.js b/path.js new file mode 100644 index 0000000..9ceee0b --- /dev/null +++ b/path.js @@ -0,0 +1,8 @@ +module.exports = { + visualPath(my_pos, target_pos) { + // visualize the path + const path = PathFinder.search(my_pos, target_pos).path; + // console.log(path) + Game.map.visual.poly(path, { stroke: '#ffffff', strokeWidth: .8, opacity: .2, lineStyle: 'dashed' }); + } +} \ No newline at end of file diff --git a/picker.js b/picker.js index 46dcfa9..154521e 100644 --- a/picker.js +++ b/picker.js @@ -1,16 +1,18 @@ //只收集,不运输 module.exports = { run(creep) { - // let sources = creep.room.find(FIND_SOURCES); - let working_target_id=creep.working_target_id; - let working_target=Game.getObjectById(working_target_id); - let Re_code=creep.harvest(working_target); - if ( Re_code== ERR_NOT_IN_RANGE) { + let working_target_id = creep.working_target_id; + let working_target = Game.getObjectById(working_target_id); + let Re_code = creep.harvest(working_target); + if (Re_code == ERR_NOT_IN_RANGE) { creep.moveTo(working_target); - }else{ - if(OK==Re_code){ + } else { + if (OK == Re_code) { creep.harvest(working_target); creep.drop(RESOURCE_ENERGY); + } else { + console.log(`${creep.name} ${creep.memory.role} working target ${working_target_id}`) + console.log(`${creep.name} ${creep.memory.role} err: ${Re_code}`) } } } diff --git a/task.js b/task.js new file mode 100644 index 0000000..b8652bc --- /dev/null +++ b/task.js @@ -0,0 +1,5 @@ +module.exports = { + upgradeController(){ + + } +} \ No newline at end of file diff --git a/test.js b/test.js new file mode 100644 index 0000000..6eec957 --- /dev/null +++ b/test.js @@ -0,0 +1,41 @@ +function Person(age, name) { + this.name = name; + this.age = age; + }; + + Object.defineProperty(Person.prototype, "age", { + get: function() { + return this._age; + }, + + // Added a few things to demonstrate additional logic on the setter + set: function(num) { + num = parseInt(num, 10); + if(num > 0) { + this._age = num; + } + } + }); + +console.log(Person.prototype.hasOwnProperty('age')) +console.log(Person.hasOwnProperty('age')) + +if(!(Person.prototype.hasOwnProperty('age'))){ + Object.defineProperty(Person.prototype, "age", { + get: function() { + return this._age; + }, + + // Added a few things to demonstrate additional logic on the setter + set: function(num) { + num = parseInt(num, 10); + if(num > 0) { + this._age = num; + } + } + }); +} + + a= new Person(1,2) + a.name=10 + console.log(a.age) \ No newline at end of file diff --git a/transfer.js b/transfer.js index 7458994..a3ce590 100644 --- a/transfer.js +++ b/transfer.js @@ -1,20 +1,24 @@ const utils=require('utils') +const path=require('path') // const harvester = require("./harvester"); module.exports = { run(creep) { if (creep.carry.energy < creep.carryCapacity) { - let harvester_array = _(Game.creeps).filter({ memory: { role: 'picker' } }).value(); - let harvester_creep=harvester_array[0]; - let target_harvester_pos=harvester_creep.pos; + let working_target_id=creep.working_target_id + let working_target=Game.getObjectById(working_target_id) + if(!working_target){ + // console.log(`${creep.name} working target vanished. Turn to unassigned.`) + return + } + let working_target_pos=working_target.pos let my_pos=creep.pos; - // console.log("distance "+utils.distance(target_harvester_pos,my_pos)) - if(utils.distance(target_harvester_pos,my_pos)>1.5){//在附近就是1或者1.414 - - creep.moveTo(target_harvester_pos); + if(utils.distance(working_target_pos,my_pos)>1.5){//在附近就是1或者1.414 + creep.moveTo(working_target_pos); + path.visualPath(creep.pos,working_target_pos); }else{ //find dropped source - let found=creep.room.lookForAt(LOOK_ENERGY,target_harvester_pos); + let found=creep.room.lookForAt(LOOK_ENERGY,working_target_pos); if(found.length>0){ creep.pickup(found[0]) } @@ -24,6 +28,7 @@ module.exports = { }else{ if (creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) { creep.moveTo(Game.spawns['Spawn1']); + path.visualPath(creep.pos,Game.spawns['Spawn1'].pos); } } }