@ -1,4 +1,10 @@
const { sum } = require ( "lodash" ) ;
const { sum , isNil } = require ( "lodash" ) ;
const STATE _INIT = 0 ;
const STATE _GOING _TO _SOURCE = 1 ;
const STATE _HARVESTING = 2 ;
const STATE _GOING _TO _DESTINATION = 3 ;
const STATE _DELIVERING = 4 ;
var roleHarvester = {
@ -15,20 +21,45 @@ var roleHarvester = {
* @ return { string } name of the new creep
* /
spawn : function ( spawn , postfix , owner _id ) {
if ( spawn . spawnCreep ( this . recommended _parts , "harvester-" + postfix , { dryRun : true } ) === OK ) {
console . log ( "roleHarvester: Spawn " + spawn . name + " is creating harvester-" + postfix + " with recommended parts ..." ) ;
spawn . spawnCreep ( this . recommended _parts , "harvester-" + postfix , { memory : { "owner" : owner _id , "role" : "Harv" } } ) ;
let creep _name = "harvester-" + postfix ;
if ( spawn . spawnCreep ( this . recommended _parts , creep _name , { dryRun : true } ) === OK ) {
console . log ( "roleHarvester: Spawn " + spawn . name + " is creating " + creep _name + " with recommended parts ..." ) ;
spawn . spawnCreep ( this . recommended _parts , creep _name , { memory : { "owner" : owner _id , "role" : "Harv" } } ) ;
}
else if ( spawn . spawnCreep ( this . minimum _parts , "harvester-" + postfix , { dryRun : true } ) === OK ) {
console . log ( "roleHarvester: Spawn " + spawn . name + " is creating harvester-"+ postfix + " with minimum parts ..." ) ;
spawn . spawnCreep ( this . minimum _parts , "harvester-" + postfix , { memory : { "owner" : owner _id , "role" : "Harv" } } ) ;
else if ( spawn . spawnCreep ( this . minimum _parts , creep _name , { dryRun : true } ) === OK ) {
console . log ( "roleHarvester: Spawn " + spawn . name + " is creating "+ creep _name + " with minimum parts ..." ) ;
spawn . spawnCreep ( this . minimum _parts , creep _name , { memory : { "owner" : owner _id , "role" : "Harv" } } ) ;
}
else {
console . log ( "roleHarvester: Spawn \"" + spawn . name + "\" couldn't afford a harvester! D: Result: " , spawn . spawnCreep ( this . minimum _parts , "harvester-" + postfix , { dryRun : true } ) ) ;
console . log ( "roleHarvester: Spawn \"" + spawn . name + "\" couldn't afford a harvester! D: Result: " , spawn . spawnCreep ( this . minimum _parts , creep _name , { dryRun : true } ) ) ;
throw "Not enough energy!" ;
}
return "harvester-" + postfix ;
Memory . creeps [ creep _name ] . harvest _spot = {
id : null ,
resource _type : null ,
structure _pos : null ,
goto _pos : null ,
} ;
Memory . creeps [ creep _name ] . destination _spot = {
id : null ,
structure _pos : null ,
goto _pos : null ,
} ;
return creep _name ;
} ,
/ * *
* Checks if the creep has all the parts necessary to work its role
* @ param { Creep } creep
* @ return bool that indicates if the creep can fullfill its role
* /
can _work : function ( creep ) {
if ( creep . getActiveBodyparts ( MOVE ) >= 1 && creep . getActiveBodyparts ( WORK ) >= 1 && creep . getActiveBodyparts ( CARRY ) >= 1 ) {
return true ;
}
return false ;
} ,
/ * *
@ -36,23 +67,183 @@ var roleHarvester = {
* @ param { Creep } creep
* /
run : function ( creep ) {
if ( creep . id === undefined ) { // id is undefined if the creep was created this tick
if ( creep . id === undefined ) { // id is undefined if the creep was created this tick, should happen only once
this . switch _state ( creep , STATE _INIT ) ;
return
}
console . log ( "roleHarvester [" + creep . name + "]: run() " + creep + " id:" , creep . id ) ;
// TODO implement state machine here about what the harvester is up to. Currently it only moves to the nearest source.
switch ( creep . memory . state ) {
case STATE _INIT :
this . init _creep ( creep ) ;
break ;
case STATE _GOING _TO _SOURCE :
if ( ! creep . spawning ) {
this . go _to _source ( creep ) ;
}
break ;
case STATE _HARVESTING :
this . harvest ( creep ) ;
break ;
case STATE _GOING _TO _DESTINATION :
this . go _to _destination ( creep ) ;
break ;
case STATE _DELIVERING :
this . delivering ( creep ) ;
break ;
default :
console . log ( "roleHarvester [" + creep . name + "]: run() unknown state!" ) ;
//this.switch_state(creep, STATE_INIT);
} ;
} ,
let goals = _ . map ( creep . room . find ( FIND _SOURCES ) , function ( source ) {
return { pos : source . pos , range : 1 } ;
} ) ;
/ * *
* Switches the state of the creep by editing the memory
* @ param { Creep } creep
* @ param { int } state State constant as given ( e . g . STATE _HARVESTING )
* /
switch _state : function ( creep , state ) {
console . log ( "roleHarvester [" + creep . name + "]: Changing state to " + state ) ;
console . log ( creep , creep . memory ) ;
creep . memory . state = state
} ,
let nearest _source = PathFinder . search ( creep . pos , goals ) ;
console . log ( "roleHarvester [" + creep . name + "]: run() moving creept towards " + nearest _source . path [ nearest _source . path . length - 1 ] , nearest _source ) ;
/ * *
* Inits creep and sets the assigned source to be the nearest source .
* @ param { * } creep
* /
init _creep : function ( creep ) { // TODO make source assignment aware of other harvesters to spread them
if ( creep . memory . harvest _spot . id !== null ) {
// harvest spot has already been given (by overlord?). Don't have to decide on my own!
}
else {
let room _sources = creep . room . find ( FIND _SOURCES ) ;
let goals = _ . map ( room _sources , function ( source ) {
return { pos : source . pos , range : 1 } ;
} ) ;
let nearest _source = PathFinder . search ( creep . pos , goals ) ;
console . log ( "roleHarvester [" + creep . name + "]: run() moving to direction " + nearest _source . path [ 0 ] ) ;
creep . moveTo ( nearest _source . path [ 0 ] ) ;
//console.log("roleHarvester ["+creep.name+"]: init_creep() remembering target position: " + nearest_source.path[nearest_source.path.length-1])
for ( let source of room _sources ) {
if ( source . pos . isNearTo ( nearest _source . path [ nearest _source . path . length - 1 ] ) ) {
creep . memory . harvest _spot . id = source . id ;
creep . memory . harvest _spot . structure _pos = source . pos ;
creep . memory . harvest _spot . goto _pos = nearest _source . path [ nearest _source . path . length - 1 ] ;
creep . memory . harvest _spot . resource _type = RESOURCE _ENERGY ;
break ;
}
}
}
if ( creep . memory . destination _spot . structure _pos !== null && creep . memory . destination _spot . goto _pos !== null ) {
// destination spot has already been given (by the overlord?). Don't have to decide on my own!
}
else if ( creep . memory . destination _spot . structure _pos !== null ) { // goto_pos === null and we have to find it on our own later
//
}
else {
console . log ( "roleHarvester [" + creep . name + "] init_creep(): Don't have a destination_spot and autonomously finding one is not implemented!" ) ;
throw "No Destination spot" ;
}
console . log ( "roleHarvester [" + creep . name + "] init_creep(): harvest task has been setup and committed to memory!" )
this . switch _state ( creep , STATE _GOING _TO _SOURCE ) ;
} ,
/ * *
* Moves the creep to its assigned source . The assigned source is a roomPosition in creep . memory . harvest _target _pos
* @ param { Creep } creep
* /
go _to _source : function ( creep ) {
if ( creep . memory . harvest _spot . goto _pos === null ) { // find goto pos, if needed
let structure _pos = new RoomPosition ( creep . memory . harvest _spot . structure _pos . x , creep . memory . harvest _spot . structure _pos . y , creep . memory . hravest _spot . structure _pos . roomName ) ;
let result = PathFinder . search ( creep . pos , { pos : structure _pos , range : 1 } ) ;
creep . memory . harvest _spot . goto _pos = result . path [ result . path . length - 1 ] ;
}
let target _pos = new RoomPosition ( creep . memory . harvest _spot . goto _pos . x , creep . memory . harvest _spot . goto _pos . y , creep . memory . harvest _spot . goto _pos . roomName ) ;
if ( creep . pos . isEqualTo ( target _pos ) ) {
console . log ( "roleHarvester [" + creep . name + "]: go_to_source() arrived at target!" ) ;
this . switch _state ( creep , STATE _HARVESTING ) ;
}
//console.log("roleHarvester ["+creep.name+"]: go_to_source() moving creep towards " + target_pos);
creep . moveTo ( target _pos , { visualizePathStyle : { stroke : '#ffaa00' } } ) ;
} ,
/ * *
* Lets the creep harvest its assigned source
* @ param { Creep } creep
* /
harvest : function ( creep ) {
if ( creep . store . getFreeCapacity ( creep . memory . harvest _spot . resource _type ) > 0 ) {
let target = Game . getObjectById ( creep . memory . harvest _spot . id ) ;
let err = creep . harvest ( target ) ;
if ( err != OK ) {
console . log ( "roleHarvester [ERROR][" + creep . name + "] harvest(): Failed to harvest at target " + target . pos + " with error: " + err ) ;
if ( err != ERR _NOT _IN _RANGE ) {
console . log ( "roleHarvester [" + creep . name + "] harvest(): Failed to harvest because of wrong goto_pos trying to recalculate and switch back to moving ..." ) ;
creep . memory . harvest _spot . structure _pos = target . pos ;
let result = PathFinder . search ( creep . pos , { pos : target . pos , range : 1 } ) ;
creep . memory . harvest _spot . goto _pos = result . path [ result . path . length - 1 ] ;
this . switch _state ( creep , STATE _GOING _TO _SOURCE ) ;
}
}
}
else {
this . switch _state ( creep , STATE _GOING _TO _DESTINATION ) ;
}
} ,
/ * *
* Goes to the delivery destination of the creep as dictated by destination _spot in its memory
* @ param { Creep } creep
* /
go _to _destination : function ( creep ) {
if ( creep . memory . destination _spot . goto _pos === null ) { // find goto pos, if needed
let structure _pos = new RoomPosition ( creep . memory . destination _spot . structure _pos . x , creep . memory . destination _spot . structure _pos . y , creep . memory . destination _spot . structure _pos . roomName ) ;
let result = PathFinder . search ( creep . pos , { pos : structure _pos , range : 1 } ) ;
creep . memory . destination _spot . goto _pos = result . path [ result . path . length - 1 ] ;
}
let target _pos = new RoomPosition ( creep . memory . destination _spot . goto _pos . x , creep . memory . destination _spot . goto _pos . y , creep . memory . destination _spot . goto _pos . roomName ) ;
if ( creep . pos . isEqualTo ( target _pos ) ) {
console . log ( "roleHarvester [" + creep . name + "]: go_to_destination() arrived at target!" ) ;
this . switch _state ( creep , STATE _DELIVERING ) ;
}
creep . moveTo ( target _pos , { visualizePathStyle : { stroke : '#ffaa00' } } ) ;
} ,
/ * *
* Lets the creep store its resources into the destination defined by the memory destination _spot
* @ param { Creep } creep
* /
delivering : function ( creep ) {
let had _issue = false ;
let storage = Game . getObjectById ( creep . memory . destination _spot . id ) ;
for ( const resource _type in creep . store ) {
console . log ( "roleHarvester [" + creep . name + "] delivering(): " + resource _type ) ;
let err = creep . transfer ( storage , resource _type ) ;
if ( err != OK ) {
had _issue = true ;
console . log ( "roleHarvester [ERROR][" + creep . name + "] delivering(): Failed to transfer resources with error: " + err ) ;
creep . say ( "ERROR!" ) ;
}
}
if ( ! had _issue ) {
this . switch _state ( creep , STATE _GOING _TO _SOURCE ) ;
}
else {
// TODO what to do if delivery failed?
}
} ,
} ;