Skip to content

Instantly share code, notes, and snippets.

@6d61726b760a
Last active June 18, 2024 15:16
Show Gist options
  • Save 6d61726b760a/247b4279003a47f8c5a82fe952da08ba to your computer and use it in GitHub Desktop.
Save 6d61726b760a/247b4279003a47f8c5a82fe952da08ba to your computer and use it in GitHub Desktop.
screeps tutorial 2024-06

Simulation mode

In this mode your script runs not on the server, but locally on your machine, so that you can pause and debug it.

View scripts on GitHub

Don't know how to code in JavaScript? Check out this free interactive course!




Welcome to Screeps!

This tutorial will help you learn basic game concepts step by step. You can take it later, but we strongly advise you to do it now, before you start a real game.

If you experience any performance issues, please note that Screeps is best played in Chrome browser.

Screeps is a game for programmers. If you don't know how to code in JavaScript, check out this free interactive course

Let's begin.




Game UI and basic scripting

This is a playing field called a "room". In the real game, rooms are connected to each other with exits, but in the simulation mode only one room is available to you.

The object in the center of the screen is your first spawn, your colony center.


You play by writing code in the panel in the bottom of the screen.

  • Click the "Console" tab.

You can enter your code in this field. It will run once.

Type anything in this field and press Enter.


Your command returns a response (or execution error) in the console below. All output is duplicated into your browser console (Ctrl+Shift+J) where you can expand objects for debugging purposes. You can open and close the bottom panel by pressing Alt+Enter.

Now we'll write something real.


Your spawn creates new units called "creeps" by its method spawnCreep. Usage of this method is described in the documentation. Each creep has a name and certain body parts that give it various skills.

You can address your spawn by its name the following way: Game.spawns['Spawn1'].

Create a worker creep with the body array [WORK,CARRY,MOVE] and name Harvester1 (the name is important for the tutorial!). You can type the code in the console yourself or copy & paste the hint below.

Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Harvester1' );

Great! You now have a creep with the name "Harvester1" that you can control.


You can see all the characteristics of your creep (or other objects) by utilizing the "View" action.


Hide the editor panel with Alt+Enter and select your creep with the help of the "View" action.


Here you can see the characteristics of the object you are now looking at. Values of each characteristic and functions of body parts are described in the documentation.


It is time to put the creep to work! This yellow square is an energy source — a valuable game resource. It can be harvested by creeps with one or more WORK body parts and transported to the spawn by creeps with CARRY parts.


To give your creep a permanently working command, the console is not enough, since we want the creep to work all the time. So we'll be using the Script tab rather than the console.

Click the "Script" tab.


Here you can write scripts that will run on a permanent basis, each game tick in a loop. It allows writing constantly working programs to control behaviour of your creeps which will work even while you are offline (in the real game only, not the Simulation Room mode).

To commit a script to the game so it can run, use this button or Ctrl+Enter.

The code for each Tutorial section is created in its own branch. You can view code from these branches for further use in your scripts.


To send a creep to harvest energy, you need to use the methods described in the documentation section below. Commands will be passed each game tick. The harvest method requires that the energy source is adjacent to the creep.

You give orders to a creep by its name this way: Game.creeps['Harvester1']. Use the FIND_SOURCES constant as an argument to the Room.find method.

Send your creep to harvest energy by typing code in the "Script" tab.


To send a creep to harvest energy, you need to use the methods described in the documentation section below. Commands will be passed each game tick. The harvest method requires that the energy source is adjacent to the creep.

You give orders to a creep by its name this way: Game.creeps['Harvester1']. Use the FIND_SOURCES constant as an argument to the Room.find method.

// main 
module.exports.loop = function () {
    var creep = Game.creeps['Harvester1'];
    var sources = creep.room.find(FIND_SOURCES);
    if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
        creep.moveTo(sources[0]);
    }
}

A bubbling yellow spot inside the creep means that it has started collecting energy from the source.


To make the creep transfer energy back to the spawn, you need to use the method Creep.transfer. However, remember that it should be done when the creep is next to the spawn, so the creep needs to walk back.

If you modify the code by adding the check .store.getFreeCapacity() > 0 to the creep, it will be able to go back and forth on its own, giving energy to the spawn and returning to the source.

  • Extend the creep program so that it can transfer harvested energy to the spawn and return back to work.

  • Documentation

// main
module.exports.loop = function () {
    var creep = Game.creeps['Harvester1'];

    if(creep.store.getFreeCapacity() > 0) {
        var sources = creep.room.find(FIND_SOURCES);
        if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
            creep.moveTo(sources[0]);
        }
    }
    else {
        if( creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE ) {
            creep.moveTo(Game.spawns['Spawn1']);
        }
    }
}

Great! This creep will now work as a harvester until it dies. Remember that almost any creep has a life cycle of 1500 game ticks, then it "ages" and dies (this behavior is disabled in the Tutorial).

Let's create another worker creep to help the first one. It will cost another 200 energy units, so you may need to wait until your harvester collects enough energy. The spawnCreep method will return an error code ERR_NOT_ENOUGH_ENERGY (-6) until then.

Remember: to execute code once just type it in the "Console" tab.

// console
Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Harvester2' );

The second creep is ready, but it won't move until we include it into the program.

To set the behavior of both creeps we could just duplicate the entire script for the second one, but it's much better to use the for loop against all the screeps in Game.creeps.

  • Expand your program to both the creeps.

  • Documentation:

// main
module.exports.loop = function () {
    for(var name in Game.creeps) {
        var creep = Game.creeps[name];

        if(creep.store.getFreeCapacity() > 0) {
            var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0]);
            }
        }
        else {
            if(creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                creep.moveTo(Game.spawns['Spawn1']);
            }
        }
    }
}

Now let's improve our code by taking the workers' behavior out into a separate module. Create a module called role.harvester with the help of the Modules section on the left of the script editor and define a run function inside the module.exports object, containing the creep behavior.

// role.harvester
var roleHarvester = {

    /** @param {Creep} creep **/
    run: function(creep) {
	    if(creep.store.getFreeCapacity() > 0) {
            var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0]);
            }
        }
        else {
            if(creep.transfer(Game.spawns['Spawn1'], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                creep.moveTo(Game.spawns['Spawn1']);
            }
        }
	}
};

module.exports = roleHarvester;

Now you can rewrite the main module code, leaving only the loop and a call to your new module by the method require('role.harvester').

Include the role.harvester module in the main module.

// main
var roleHarvester = require('role.harvester');

module.exports.loop = function () {

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        roleHarvester.run(creep);
    }
}

It's much better now!

By adding new roles and modules to your creeps this way, you can control and manage the work of many creeps. In the next Tutorial section, we’ll develop a new creep role.




Upgrading Controller

In this Tutorial section we’ll talk about a key strategic object in your room: Room Controller. By controlling this invincible structure you can build facilities in the room. The higher the controller level, the more structures available to build.


You will need a new worker creep to upgrade your controller level. Let's call it "Upgrader1". In following sections we'll discuss how to create creeps automatically, but for now let's send a command manually to the console.

// console
Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Upgrader1' );

Creep "Upgrader1" went to perform the same task as the harvester, but we don't want it to. We need to differentiate creep roles.


To do that, we need to utilize the memory property of each creep that allows writing custom information into the creep's "memory". Let's do this to assign different roles to our creeps.

All your stored memory is accessible via the global Memory object. You can use it any way you like.

Write a property role='harvester' into the memory of the harvester creep and role='upgrader' — to the upgrader creep with the help of the console.

// main
Game.creeps['Harvester1'].memory.role = 'harvester';
Game.creeps['Upgrader1'].memory.role = 'upgrader';

You can check your creeps' memory in either the creep information panel on the left or on the "Memory" tab.

Now let's define the behavior of the new creep. Both creeps should harvest energy, but the creep with the role harvester should bring it to the spawn, while the creep with the role upgrader should go to the Controller and apply the function upgradeController to it (you can get the Controller object with the help of the Creep.room.controller property).

In order to do this, we’ll create a new module called role.upgrader.

Create a new module role.upgrader with the behavior logic of your new creep.

// role.upgrader
var roleUpgrader = {

    /** @param {Creep} creep **/
    run: function(creep) {
	    if(creep.store[RESOURCE_ENERGY] == 0) {
            var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0]);
            }
        }
        else {
            if(creep.upgradeController(creep.room.controller) == ERR_NOT_IN_RANGE) {
                creep.moveTo(creep.room.controller);
            }
        }
	}
};

module.exports = roleUpgrader;

In our main module, all creeps run the same role. We need to divide their behavior depending on the previously defined property Creep.memory.role by connecting the new module.

Apply the logic from the module role.upgrader to the creep with the role upgrader and check how it performed.

// main 
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');

module.exports.loop = function () {

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
    }
}

Perfect, you have upgraded your Controller level!

Important: If you don’t upgrade your Controller within 20,000 game ticks, it loses one level. On reaching level 0, you will lose control over the room, and another player will be able to capture it freely. Make sure that at least one of your creeps regularly performs the function upgradeController.




Bulding Structures

The Controller upgrade gives access to some new structures: walls, ramparts, and extensions. We’ll discuss walls and ramparts in the next Tutorial section, for now let’s talk about extensions.

Extensions are required to build larger creeps. A creep with only one body part of one type works poorly. Giving it several WORKs will make him work proportionally faster.

However, such a creep will be costly and a lone spawn can only contain 300 energy units. To build creeps costing over 300 energy units you need spawn extensions.


The second Controller level has 5 extensions available for you to build. This number increases with each new level.

You can place extensions at any spot in your room, and a spawn can use them regardless of the distance. In this Tutorial we have already placed corresponding construction sites for your convenience.


Let’s create a new creep whose purpose is to build structures. This process will be similar to the previous Tutorial sections. But this time let’s set memory for the new creep right in the method Spawn.spawnCreep by passing it in the third argument.

Spawn a creep with the body [WORK,CARRY,MOVE], the name Builder1, and {role:'builder'} as its memory.

// console
Game.spawns['Spawn1'].spawnCreep( [WORK, CARRY, MOVE], 'Builder1',
    { memory: { role: 'builder' } } );

Our new creep won’t move until we define the behavior for the role builder.


As before, let’s move this role into a separate module role.builder. The building is carried out by applying the method Creep.build to the construction sites searchable by Room.find(FIND_CONSTRUCTION_SITES). The structure requires energy which your creep can harvest on its own.

To avoid having the creep run back and forth too often but make it deplete the cargo, let’s complicate our logic by creating a new Boolean variable creep.memory.building which will tell the creep when to switch tasks. We'll also add new creep.say call and visualizePathStyle option to the moveTo method to visualize the creep's intentions.

Create the module role.builder with a behavior logic for a new creep.

// role.builder
var roleBuilder = {

    /** @param {Creep} creep **/
    run: function(creep) {

	    if(creep.memory.building && creep.store[RESOURCE_ENERGY] == 0) {
            creep.memory.building = false;
            creep.say('🔄 harvest');
	    }
	    if(!creep.memory.building && creep.store.getFreeCapacity() == 0) {
	        creep.memory.building = true;
	        creep.say('🚧 build');
	    }

	    if(creep.memory.building) {
	        var targets = creep.room.find(FIND_CONSTRUCTION_SITES);
            if(targets.length) {
                if(creep.build(targets[0]) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(targets[0], {visualizePathStyle: {stroke: '#ffffff'}});
                }
            }
	    }
	    else {
	        var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0], {visualizePathStyle: {stroke: '#ffaa00'}});
            }
	    }
	}
};

module.exports = roleBuilder;

Let’s create a call of the new role in the main module and wait for the result.

By using the module role.builder in the new creep, build all 5 extensions.

// main
var roleHarvester = require('role.harvester');
var roleBuilder = require('role.builder');

module.exports.loop = function () {

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
    }
}

Your extensions have been built. Now let’s learn to work with them.


Maintaining extensions requires you to teach your harvesters to carry energy not just to a spawn but also to extensions. To do this, you can either use the Game.structures object or search within the room with the help of Room.find(FIND_STRUCTURES). In both cases, you will need to filter the list of items on the condition structure.structureType == STRUCTURE_EXTENSION (or, alternatively, structure instanceof StructureExtension) and also check them for energy load, as before.

Refine the logic in the module role.harvester.

//role.harvester
var roleHarvester = {

    /** @param {Creep} creep **/
    run: function(creep) {
	    if(creep.store.getFreeCapacity() > 0) {
            var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0], {visualizePathStyle: {stroke: '#ffaa00'}});
            }
        }
        else {
            var targets = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                        return (structure.structureType == STRUCTURE_EXTENSION || structure.structureType == STRUCTURE_SPAWN) &&
                            structure.store.getFreeCapacity(RESOURCE_ENERGY) > 0;
                    }
            });
            if(targets.length > 0) {
                if(creep.transfer(targets[0], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(targets[0], {visualizePathStyle: {stroke: '#ffffff'}});
                }
            }
        }
	}
};

module.exports = roleHarvester;

To know the total amount of energy in the room, you can use the property Room.energyAvailable. Let’s add the output of this property into the console in order to track it during the filling of extensions.

Fill all the 5 extensions and the spawn with energy.

// main
var roleHarvester = require('role.harvester');
var roleBuilder = require('role.builder');

module.exports.loop = function () {

    for(var name in Game.rooms) {
        console.log('Room "'+name+'" has '+Game.rooms[name].energyAvailable+' energy');
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
    }
}

Excellent, all the structures are filled with energy. It’s time to build somebody large!


In total, we have 550 energy units in our spawn and extensions. It is enough to build a creep with the body [WORK,WORK,WORK,WORK,CARRY,MOVE,MOVE]. This creep will work 4 times faster than a regular worker creep. Its body is heavier, so we’ll add another MOVE to it. However, two parts are still not enough to move it at the speed of a small fast creep which would require 4xMOVEs or building a road.

Spawn a creep with the body [WORK,WORK,WORK,CARRY,MOVE,MOVE], the name HarvesterBig, and harvester role.

// console
Game.spawns['Spawn1'].spawnCreep( [WORK,WORK,WORK,WORK,CARRY,MOVE,MOVE],
    'HarvesterBig',
    { memory: { role: 'harvester' } } );

Building this creep took energy from all storages and completely drained them.

Now let’s select our creep and watch it work.

Click on the creep Harvester2.


As you can see on the right panel, this powerful creep harvests 8 energy units per tick. A few such creeps can completely drain an energy source before it refills thus giving your colony a maximum energy boost.


Hence, by upgrading your Controller, constructing new extensions and more powerful creeps, you considerably improve the effectiveness of your colony work. Also, by replacing a lot of small creeps with fewer large ones, you save CPU resources on controlling them which is an important prerequisite to play in the online mode.

In the next section, we’ll talk about how to set up the automatic manufacturing of new creeps.




Autospawning Creeps

Until now, we have created new creeps directly in the console. It’s not a good idea to do it constantly since the very idea of Screeps is making your colony control itself. You will do well if you teach your spawn to produce creeps in the room on its own.

This is a rather complicated topic and many players spend months perfecting and refining their auto-spawning code. But let’s try at least something simple and master some basic principles to start with.


You will have to create new creeps when old ones die from age or some other reasons. Since there are no events in the game to report death of a particular creep, the easiest way is to just count the number of required creeps, and if it becomes less than a defined value, to start spawning.

There are several ways to count the number of creeps of the required type. One of them is filtering Game.creeps with the help of the _.filter function and using the role in their memory. Let’s try to do that and bring the number of creeps into the console.

Add the output of the number of creeps with the role harvester into the console.

// main 
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');

module.exports.loop = function () {

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
    console.log('Harvesters: ' + harvesters.length);

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
    }
}

Let’s say we want to have at least two harvesters at any time. The easiest way to achieve this is to run StructureSpawn.spawnCreep each time we discover it’s less than this number. You may not define its name (it will be given automatically in this case), but don’t forget to define the needed role.

We may also add some new RoomVisual call in order to visualize what creep is being spawned.

Add the logic for StructureSpawn.spawnCreep in your main module.

// main
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');

module.exports.loop = function () {

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
    console.log('Harvesters: ' + harvesters.length);

    if(harvesters.length < 2) {
        var newName = 'Harvester' + Game.time;
        console.log('Spawning new harvester: ' + newName);
        Game.spawns['Spawn1'].spawnCreep([WORK,CARRY,MOVE], newName, 
            {memory: {role: 'harvester'}});        
    }
    
    if(Game.spawns['Spawn1'].spawning) { 
        var spawningCreep = Game.creeps[Game.spawns['Spawn1'].spawning.name];
        Game.spawns['Spawn1'].room.visual.text(
            '🛠️' + spawningCreep.memory.role,
            Game.spawns['Spawn1'].pos.x + 1, 
            Game.spawns['Spawn1'].pos.y, 
            {align: 'left', opacity: 0.8});
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
    }
}

Now let’s try to emulate a situation when one of our harvesters dies. You can now give the command suicide to the creep via the console or its properties panel on the right.

Make one of the harvesters suicide.

// console
Game.creeps['Harvester1'].suicide()

As you can see from the console, after we lacked one harvester, the spawn instantly started building a new one with a new name.


An important point here is that the memory of dead creeps is not erased but kept for later reuse. If you create creeps with random names each time it may lead to memory overflow, so you should clear it in the beginning of each tick (prior to the creep creation code).

Add code to clear the memory.

// main
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');

module.exports.loop = function () {

    for(var name in Memory.creeps) {
        if(!Game.creeps[name]) {
            delete Memory.creeps[name];
            console.log('Clearing non-existing creep memory:', name);
        }
    }

    var harvesters = _.filter(Game.creeps, (creep) => creep.memory.role == 'harvester');
    console.log('Harvesters: ' + harvesters.length);

    if(harvesters.length < 2) {
        var newName = 'Harvester' + Game.time;
        console.log('Spawning new harvester: ' + newName);
        Game.spawns['Spawn1'].spawnCreep([WORK,CARRY,MOVE], newName, 
            {memory: {role: 'harvester'}});
    }
    
    if(Game.spawns['Spawn1'].spawning) { 
        var spawningCreep = Game.creeps[Game.spawns['Spawn1'].spawning.name];
        Game.spawns['Spawn1'].room.visual.text(
            '🛠️' + spawningCreep.memory.role,
            Game.spawns['Spawn1'].pos.x + 1, 
            Game.spawns['Spawn1'].pos.y, 
            {align: 'left', opacity: 0.8});
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
    }
}

Now the memory of the deceased is relegated to oblivion which saves us resources.

Apart from creating new creeps after the death of old ones, there is another way to maintain the needed number of creeps: the method StructureSpawn.renewCreep. Creep aging is disabled in the Tutorial, so we recommend that you familiarize yourself with it on your own.




Defending Your Room

The world of Screeps is not the safest place. Other players may have claims on your territory. Besides, your room may be raided by neutral NPC creeps occasionally. So you ought to think about your colony defense in order to develop it successfully.


This hostile creep has come from the left entry and attacked your colony. It’s good that we have walls to restrain it temporarily. But they will fall sooner or later, so we need to deal with the problem.


The surest way to fend off an attack is using the room Safe Mode. In safe mode, no other creep will be able to use any harmful methods in the room (but you’ll still be able to defend against strangers).

The safe mode is activated via the room controller which should have activations available to use. Let’s spend one activation to turn it on in our room.

Activate safe mode.

// console 
Game.spawns['Spawn1'].room.controller.activateSafeMode();

As you can see, the enemy creep stopped attacking the wall – its harmful methods are blocked. We recommend that you activate safe mode when your defenses fail.

Now let’s cleanse the room from unwanted guests.


Towers are the easiest way to actively defend a room. They use energy and can be targeted at any creep in a room to attack or heal it. The effect depends on the distance between the tower and the target.

To start with, let’s lay a foundation for our new tower. You can set any place you wish inside the walls and place the construction site there with the help of the button “Construct” on the upper panel.

Place the construction site for the tower (manually or using the code below).

// console 
Game.spawns['Spawn1'].room.createConstructionSite( 23, 22, STRUCTURE_TOWER );

The creep Builder1 has immediately started the construction. Let’s wait until it finishes.


A tower uses energy, so let’s set the harvester role to bring energy to the tower along with other structures. To do this, you need to add the constant STRUCTURE_TOWER to the filter of structures your harvester is aimed at.

Add STRUCTURE_TOWER to the module role.harvester and wait for the energy to appear in the tower.

// role.harvester 

var roleHarvester = {

    /** @param {Creep} creep **/
    run: function(creep) {
	    if(creep.store.getFreeCapacity() > 0) {
            var sources = creep.room.find(FIND_SOURCES);
            if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE) {
                creep.moveTo(sources[0], {visualizePathStyle: {stroke: '#ffaa00'}});
            }
        }
        else {
            var targets = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                        return (structure.structureType == STRUCTURE_EXTENSION ||
                                structure.structureType == STRUCTURE_SPAWN ||
                                structure.structureType == STRUCTURE_TOWER) && 
                                structure.store.getFreeCapacity(RESOURCE_ENERGY) > 0;
                    }
            });
            if(targets.length > 0) {
                if(creep.transfer(targets[0], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(targets[0], {visualizePathStyle: {stroke: '#ffffff'}});
                }
            }
        }
	}
};

module.exports = roleHarvester;

Excellent, your tower is ready to use!

Like a creep, a tower has several similar methods: attack, heal, and repair. Each action spends 10 energy units. We need to use attack on the closest enemy creep upon its discovery. Remember that distance is vital: the effect can be several times stronger with the same energy cost!

To get the tower object directly you can use its ID from the right panel and the method Game.getObjectById.

Destroy the enemy creep with the help of the tower.

// main

var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');

module.exports.loop = function () {

    var tower = Game.getObjectById('f852f2b15242d901ac9eca93');
    if(tower) {
        var closestHostile = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
        if(closestHostile) {
            tower.attack(closestHostile);
        }
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
    }
}

The enemy creep is eliminated and our colony can breathe easy. However, the invader has damaged some walls during the brief attack. You’d better set up auto-repair.


Damaged structures can be repaired by both creeps and towers. Let’s try to use a tower for that. We’ll need the method repair. You will also need the method Room.find and a filter to locate the damaged walls.

Note that since walls don’t belong to any player, finding them requires the constant FIND_STRUCTURES rather than FIND_MY_STRUCTURES.

Repair all the damaged walls.

// main
var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');

module.exports.loop = function () {

    var tower = Game.getObjectById('f852f2b15242d901ac9eca93');
    if(tower) {
        var closestDamagedStructure = tower.pos.findClosestByRange(FIND_STRUCTURES, {
            filter: (structure) => structure.hits < structure.hitsMax
        });
        if(closestDamagedStructure) {
            tower.repair(closestDamagedStructure);
        }

        var closestHostile = tower.pos.findClosestByRange(FIND_HOSTILE_CREEPS);
        if(closestHostile) {
            tower.attack(closestHostile);
        }
    }

    for(var name in Game.creeps) {
        var creep = Game.creeps[name];
        if(creep.memory.role == 'harvester') {
            roleHarvester.run(creep);
        }
        if(creep.memory.role == 'upgrader') {
            roleUpgrader.run(creep);
        }
        if(creep.memory.role == 'builder') {
            roleBuilder.run(creep);
        }
    }
}

All the damage from the attack has been repaired!

Congratulations, you have completed the Tutorial! Now you have enough knowledge and code to start playing in the online mode. Choose your room, found a colony, and set out on your own quest for domination in the world of Screeps!

If you want to delve deeper in the subtleties of the game or have any questions, please feel free to refer to:

Have fun scripting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment