Skip to content

Commit

Permalink
1.3 Release: add Tasks.chain(), add Tasks.withdrawAll, and fixes bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
bencbartlett committed Aug 1, 2018
1 parent 7c49da6 commit e41540b
Show file tree
Hide file tree
Showing 19 changed files with 431 additions and 124 deletions.
269 changes: 203 additions & 66 deletions bin/creep-tasks.js

Large diffs are not rendered by default.

11 changes: 4 additions & 7 deletions examples/JavaScript/role.patroller.js
Expand Up @@ -3,15 +3,12 @@ let Tasks = require('creep-tasks');
let rolePatroller = {

// Patroller will patrol in a cycle from Spawn1 to all placed flags.
// This role demonstrates using parents, via Task.fork(), with creep-tasks.
// This role demonstrates using parents, via Task.chain(), with creep-tasks.

newTask: function (creep) {
let flagNames = _.keys(Game.flags);
creep.task = Tasks.goTo(Game.spawns['Spawn1']);
for (let name of flagNames) {
let nextTask = Tasks.goTo(Game.flags[name]);
creep.task.fork(nextTask); // Task.fork() suspends the current task and makes it the new task's parent
}
let flags = _.values(Game.flags);
let tasks = _.map(flags, flag => Tasks.goTo(flag));
creep.task = Tasks.chain(tasks);
}

};
Expand Down
11 changes: 4 additions & 7 deletions examples/TypeScript/roles/patroller.ts
Expand Up @@ -3,15 +3,12 @@ import {Tasks} from '../../../src/creep-tasks/Tasks'; // Path to Tasks.ts
export class RolePatroller {

// Patroller will patrol in a cycle from Spawn1 to all placed flags.
// This role demonstrates using parents, via Task.fork(), with creep-tasks.
// This role demonstrates using parents, via Task.chain(), with creep-tasks.

static newTask(creep: Creep) {
let flagNames = _.keys(Game.flags);
creep.task = Tasks.goTo(Game.spawns['Spawn1']);
for (let name of flagNames) {
let nextTask = Tasks.goTo(Game.flags[name]);
creep.task.fork(nextTask); // Task.fork() suspends the current task and makes it the new task's parent
}
let flags = _.values(Game.flags);
let tasks = _.map(flags, flag => Tasks.goTo(flag));
creep.task = Tasks.chain(tasks);
}

}
Expand Down
4 changes: 2 additions & 2 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "creep-tasks",
"version": "1.2.0",
"version": "1.3.0",
"description": "Tasks for your creeps",
"author": "Ben Bartlett",
"repository": {
Expand Down Expand Up @@ -31,7 +31,7 @@
"typescript": "^2.7.2"
},
"dependencies": {
"@types/screeps": "^2.3.0"
"@types/screeps": "^2.4.0"
},
"files": [
"dist/**/*",
Expand Down
11 changes: 6 additions & 5 deletions src/creep-tasks/Task.ts
Expand Up @@ -68,8 +68,8 @@ export abstract class Task implements ITask {
oneShot : false, // remove this task once work() returns OK, regardless of validity
};
_.defaults(options, {
blind : false,
travelToOptions: {},
blind : false,
moveOptions: {},
});
this.tick = Game.time;
this.options = options;
Expand Down Expand Up @@ -207,7 +207,7 @@ export abstract class Task implements ITask {
}
}

move(range = this.settings.targetRange): number {
moveToTarget(range = this.settings.targetRange): number {
if (this.options.moveOptions && !this.options.moveOptions.range) {
this.options.moveOptions.range = range;
}
Expand All @@ -232,7 +232,7 @@ export abstract class Task implements ITask {
}

// Execute this task each tick. Returns nothing unless work is done.
run(): number | void {
run(): number | undefined {
if (this.creep.pos.inRangeTo(this.targetPos, this.settings.targetRange) && !this.creep.pos.isEdge) {
if (this.settings.workOffRoad) {
// Move to somewhere nearby that isn't on a road
Expand All @@ -244,7 +244,7 @@ export abstract class Task implements ITask {
}
return result;
} else {
this.move();
this.moveToTarget();
}
}

Expand Down Expand Up @@ -283,6 +283,7 @@ export abstract class Task implements ITask {

// Finalize the task and switch to parent task (or null if there is none)
finish(): void {
this.moveToNextPos();
if (this.creep) {
this.creep.task = this.parent;
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/creep-tasks/TaskInstances/task_attack.ts
Expand Up @@ -33,7 +33,7 @@ export class TaskAttack extends Task {
if (creep.pos.isNearTo(target)) {
attackReturn = creep.attack(target);
} else {
attackReturn = this.move(1); // approach target if you also have attack parts
attackReturn = this.moveToTarget(1); // approach target if you also have attack parts
}
}
if (creep.pos.inRangeTo(target, 3) && creep.getActiveBodyparts(RANGED_ATTACK) > 0) {
Expand Down
77 changes: 68 additions & 9 deletions src/creep-tasks/TaskInstances/task_getBoosted.ts
@@ -1,33 +1,92 @@
import {Task} from '../Task';

export const MIN_LIFETIME_FOR_BOOST = 0.9;

export type getBoostedTargetType = StructureLab;

function boostCounts(creep: Creep): { [boostType: string]: number } {
return _.countBy(this.body as BodyPartDefinition[], bodyPart => bodyPart.boost);
}

const boostParts: { [boostType: string]: BodyPartConstant } = {

'UH': ATTACK,
'UO': WORK,
'KH': CARRY,
'KO': RANGED_ATTACK,
'LH': WORK,
'LO': HEAL,
'ZH': WORK,
'ZO': MOVE,
'GH': WORK,
'GO': TOUGH,

'UH2O': ATTACK,
'UHO2': WORK,
'KH2O': CARRY,
'KHO2': RANGED_ATTACK,
'LH2O': WORK,
'LHO2': HEAL,
'ZH2O': WORK,
'ZHO2': MOVE,
'GH2O': WORK,
'GHO2': TOUGH,

'XUH2O': ATTACK,
'XUHO2': WORK,
'XKH2O': CARRY,
'XKHO2': RANGED_ATTACK,
'XLH2O': WORK,
'XLHO2': HEAL,
'XZH2O': WORK,
'XZHO2': MOVE,
'XGH2O': WORK,
'XGHO2': TOUGH,

};

export class TaskGetBoosted extends Task {
static taskName = 'getBoosted';
target: getBoostedTargetType;

constructor(target: getBoostedTargetType, amount: number | undefined = undefined, options = {} as TaskOptions) {
data: {
resourceType: _ResourceConstantSansEnergy;
amount: number | undefined;
};

constructor(target: getBoostedTargetType,
boostType: _ResourceConstantSansEnergy,
partCount: number | undefined = undefined,
options = {} as TaskOptions) {
super(TaskGetBoosted.taskName, target, options);
// Settings
this.data.amount = amount;
this.data.resourceType = boostType;
this.data.amount = partCount;

}

isValidTask() {
if (this.data.amount && this.target.mineralType) {
let boostCounts = _.countBy(this.creep.body, bodyPart => bodyPart.boost);
return boostCounts[this.target.mineralType] <= this.data.amount;
} else {
let boosts = _.compact(_.unique(_.map(this.creep.body, bodyPart => bodyPart.boost)));
return !boosts.includes(this.target.mineralType);
let lifetime = _.any(this.creep.body, part => part.type == CLAIM) ? CREEP_CLAIM_LIFE_TIME : CREEP_LIFE_TIME;
if (this.creep.ticksToLive && this.creep.ticksToLive < MIN_LIFETIME_FOR_BOOST * lifetime) {
return false; // timeout after this amount of lifespan has passed
}
let partCount = (this.data.amount || this.creep.getActiveBodyparts(boostParts[this.data.resourceType]));
return (boostCounts(this.creep)[this.data.resourceType] || 0) < partCount;
}

isValidTarget() {
return true; // Warning: this will block creep actions if the lab is left unsupplied of energy or minerals
}

work() {
return this.target.boostCreep(this.creep);
let partCount = (this.data.amount || this.creep.getActiveBodyparts(boostParts[this.data.resourceType]));
if (this.target.mineralType == this.data.resourceType &&
this.target.mineralAmount >= LAB_BOOST_MINERAL * partCount &&
this.target.energy >= LAB_BOOST_ENERGY * partCount) {
return this.target.boostCreep(this.creep, this.data.amount);
} else {
return ERR_NOT_FOUND;
}
}
}

Expand Down
10 changes: 7 additions & 3 deletions src/creep-tasks/TaskInstances/task_goTo.ts
Expand Up @@ -2,15 +2,19 @@ import {Task} from '../Task';

export type goToTargetType = { pos: RoomPosition } | RoomPosition;

function hasPos(obj: { pos: RoomPosition } | RoomPosition): obj is { pos: RoomPosition } {
return (<{ pos: RoomPosition } >obj).pos != undefined;
}

export class TaskGoTo extends Task {
static taskName = 'goTo';
target: null;

constructor(target: goToTargetType, options = {} as TaskOptions) {
if (target instanceof RoomPosition) {
super(TaskGoTo.taskName, {ref: '', pos: target}, options);
} else {
if (hasPos(target)) {
super(TaskGoTo.taskName, {ref: '', pos: target.pos}, options);
} else {
super(TaskGoTo.taskName, {ref: '', pos: target}, options);
}
// Settings
this.settings.targetRange = 1;
Expand Down
19 changes: 16 additions & 3 deletions src/creep-tasks/TaskInstances/task_harvest.ts
@@ -1,6 +1,10 @@
import {Task} from '../Task';

export type harvestTargetType = Source;
export type harvestTargetType = Source | Mineral;

function isSource(obj: Source | Mineral): obj is Source {
return (<Source>obj).energy != undefined;
}

export class TaskHarvest extends Task {

Expand All @@ -12,11 +16,20 @@ export class TaskHarvest extends Task {
}

isValidTask() {
return this.creep.carry.energy < this.creep.carryCapacity;
return _.sum(this.creep.carry) < this.creep.carryCapacity;
}

isValidTarget() {
return this.target && this.target.energy > 0;
// if (this.target && (this.target instanceof Source ? this.target.energy > 0 : this.target.mineralAmount > 0)) {
// // Valid only if there's enough space for harvester to work - prevents doing tons of useless pathfinding
// return this.target.pos.availableNeighbors().length > 0 || this.creep.pos.isNearTo(this.target.pos);
// }
// return false;
if (isSource(this.target)) {
return this.target.energy > 0;
} else {
return this.target.mineralAmount > 0;
}
}

work() {
Expand Down
2 changes: 1 addition & 1 deletion src/creep-tasks/TaskInstances/task_heal.ts
Expand Up @@ -25,7 +25,7 @@ export class TaskHeal extends Task {
if (this.creep.pos.isNearTo(this.target)) {
return this.creep.heal(this.target);
} else {
this.move(1);
this.moveToTarget(1);
}
return this.creep.rangedHeal(this.target);
}
Expand Down
10 changes: 9 additions & 1 deletion src/creep-tasks/TaskInstances/task_repair.ts
Expand Up @@ -22,6 +22,14 @@ export class TaskRepair extends Task {
}

work() {
return this.creep.repair(this.target);
let result = this.creep.repair(this.target);
if (this.target.structureType == STRUCTURE_ROAD) {
// prevents workers from idling for a tick before moving to next target
let newHits = this.target.hits + this.creep.getActiveBodyparts(WORK) * REPAIR_POWER;
if (newHits > this.target.hitsMax) {
this.finish();
}
}
return result;
}
}
15 changes: 13 additions & 2 deletions src/creep-tasks/TaskInstances/task_transferAll.ts
Expand Up @@ -8,12 +8,20 @@ export class TaskTransferAll extends Task {
static taskName = 'transferAll';
target: transferAllTargetType;

constructor(target: transferAllTargetType, options = {} as TaskOptions) {
data: {
skipEnergy?: boolean;
};

constructor(target: transferAllTargetType, skipEnergy = false, options = {} as TaskOptions) {
super(TaskTransferAll.taskName, target, options);
this.data.skipEnergy = skipEnergy;
}

isValidTask() {
for (let resourceType in this.creep.carry) {
if (this.data.skipEnergy && resourceType == RESOURCE_ENERGY) {
continue;
}
let amountInCarry = this.creep.carry[<ResourceConstant>resourceType] || 0;
if (amountInCarry > 0) {
return true;
Expand All @@ -23,11 +31,14 @@ export class TaskTransferAll extends Task {
}

isValidTarget() {
return this.target.storeCapacity - _.sum(this.target.store) >= _.sum(this.creep.carry);
return _.sum(this.target.store) < this.target.storeCapacity;
}

work() {
for (let resourceType in this.creep.carry) {
if (this.data.skipEnergy && resourceType == RESOURCE_ENERGY) {
continue;
}
let amountInCarry = this.creep.carry[<ResourceConstant>resourceType] || 0;
if (amountInCarry > 0) {
return this.creep.transfer(this.target, <ResourceConstant>resourceType);
Expand Down
5 changes: 3 additions & 2 deletions src/creep-tasks/TaskInstances/task_withdraw.ts
Expand Up @@ -8,7 +8,8 @@ export type withdrawTargetType =
| StoreStructure
| StructureLab
| StructureNuker
| StructurePowerSpawn;
| StructurePowerSpawn
| Tombstone;

export class TaskWithdraw extends Task {

Expand Down Expand Up @@ -38,7 +39,7 @@ export class TaskWithdraw extends Task {
isValidTarget() {
let amount = this.data.amount || 1;
let target = this.target;
if (isStoreStructure(target)) {
if (target instanceof Tombstone || isStoreStructure(target)) {
return (target.store[this.data.resourceType] || 0) >= amount;
} else if (isEnergyStructure(target) && this.data.resourceType == RESOURCE_ENERGY) {
return target.energy >= amount;
Expand Down
32 changes: 32 additions & 0 deletions src/creep-tasks/TaskInstances/task_withdrawAll.ts
@@ -0,0 +1,32 @@
import {Task} from '../Task';


export type withdrawAllTargetType = StructureStorage | StructureTerminal | StructureContainer | Tombstone;

export class TaskWithdrawAll extends Task {

static taskName = 'withdrawAll';
target: withdrawAllTargetType;

constructor(target: withdrawAllTargetType, options = {} as TaskOptions) {
super(TaskWithdrawAll.taskName, target, options);
}

isValidTask() {
return (_.sum(this.creep.carry) < this.creep.carryCapacity);
}

isValidTarget() {
return _.sum(this.target.store) > 0;
}

work() {
for (let resourceType in this.target.store) {
let amountInStore = this.target.store[<ResourceConstant>resourceType] || 0;
if (amountInStore > 0) {
return this.creep.withdraw(this.target, <ResourceConstant>resourceType);
}
}
return -1;
}
}

0 comments on commit e41540b

Please sign in to comment.