{"id":31049260,"url":"https://github.com/captemulation/screeps-redux","last_synced_at":"2026-03-15T07:40:16.420Z","repository":{"id":39763516,"uuid":"158590993","full_name":"CaptEmulation/screeps-redux","owner":"CaptEmulation","description":"Screeps Bot implemented in Redux because why not?","archived":false,"fork":false,"pushed_at":"2023-03-07T02:35:16.000Z","size":1576,"stargazers_count":4,"open_issues_count":8,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-03-25T13:18:46.219Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CaptEmulation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-21T18:33:43.000Z","updated_at":"2021-12-21T00:29:34.000Z","dependencies_parsed_at":"2023-02-07T16:45:23.879Z","dependency_job_id":null,"html_url":"https://github.com/CaptEmulation/screeps-redux","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"purl":"pkg:github/CaptEmulation/screeps-redux","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptEmulation%2Fscreeps-redux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptEmulation%2Fscreeps-redux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptEmulation%2Fscreeps-redux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptEmulation%2Fscreeps-redux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CaptEmulation","download_url":"https://codeload.github.com/CaptEmulation/screeps-redux/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaptEmulation%2Fscreeps-redux/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275174427,"owners_count":25418064,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-14T21:48:40.228Z","updated_at":"2026-03-15T07:40:11.378Z","avatar_url":"https://github.com/CaptEmulation.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# screeps-redux\n\nOur bot for Screeps. Originally strongly based on redux and redux-saga, now only loosely so.\n\n## Getting Started\n\nSome global functions are present to help pick a starting location. First place a spawn anywhere in the world. This will allow you to execute console commands. From there you can locate an optimal location for the first spawn in any room (even if you do not have vision). A visual onscreen display of potential spawn location will be shown. Lower numbers are better.\n\n```\ngetSpawnLocation({ room: 'E21S9', sources: [[38,27], [42,12]], controller: [26, 24], mineral: [44,29] })\n```\n\nEnter the correct source and mineral locations for a room. If necessary respawn and then put your spawn at the location specified on the console.\n\nAdd the `bootstrap` task to the new room.\n\n```\nGame.rooms['roomName'].addTask('bootstrap');\n```\n\nThat's it! As the room controller is leveled up, the \"bunker\" will have its buildings placed automatically. However, roads outside the bunker and walls/ramparts are not yet placed automatically. Placing construction sites will spawn builders that will construct and then recycle themselves when done.\n\nFor RCL1 and RCL2, \"pioneer\" creeps will be spawned to harvest, supply spawn with energy and upgrade controller. At RCL3 containers will be automatically be constructed at the controller and sources. When those are done then pioneers will recycle themselves to be replaced by separate upgraders, static miners and haulers.\n\n## Mining remote rooms\n\nRooms can support remote mining at RCL3. To configure a spawner to support remote mining:\n\n```\nGame.spawns['Spawn1'].addTask('remoteMine', { rooms: ['room1', 'room2'] });\n```\n\n## Claiming additional rooms\n\nA room can be instructed to create a claimer and pioneers for a new room with the following command\n\n```\nGame.rooms['rcl3 or greater room'].addTask('claim', {\n  targets: ['roomName to claim', 'another room if you are feeling greedy']\n});\n```\n\nThat's it! The room claim task will instruct the spawner to build claimers and pioneers targeting each room to claim the room and create a new bunker layout in the remote room. The source room will continue to support the remote room with pioneers until it gets to rcl3.\n\n## Get out of the way\n\n`Creep.getAllCreepsOutOfTheWay` expects creeps to have a `target` and optionally a `range` saved to memory. This is used to find optimal locations to move creeps out of the way\n\n## Tasks\n\nGenerator based task system for game objects with memory. Tasks can be added to rooms, spawns and creeps.\n\nExample:\n\n```\n// Basic task\nsomeCreep.addTask('builder');\n// Task with options\nsomeCreep.addTask('harvest', {\n  sourceId: source.id,\n});\n```\n\nOptions passed into a task are added to the task context (see below)\n\n### Definition\n\nTasks are generator functions that accept a game instance and a utility object.\n\nExample:\n\n```\nexport function* construct(creep, {\n  priority,\n  done,\n  context,\n}) {\n  yield priority();\n  if (_.sum(creep.carry) === 0) {\n    delete creep.memory.target;\n    delete creep.memory.range;\n    yield done();\n  }\n  const myConstructionSites = creep.room.find(FIND_MY_CONSTRUCTION_SITES);\n  if (!myConstructionSites.length) {\n    yield done({\n      noTarget: true,\n    });\n  }\n  // Pick a construction site\n  const target = findWorkSites(myConstructionSites);\n  const range = creep.pos.getRangeTo(target);\n  if (range \u003e 3) {\n    creep.routeTo(target, { range: 3 });\n  } else {\n    creep.memory.target = target.id;\n    creep.memory.range = 3;\n    creep.build(target);\n  }\n}\n\nexport function* supplySpawn(creep, {\n  priority,\n  done,\n  context,\n}) {\n  yield priority();\n  if (creep.carry[RESOURCE_ENERGY] === 0) {\n    delete creep.memory.target;\n    return yield done();\n  }\n  const targets = creep.room.find(FIND_MY_STRUCTURES, {\n    filter: and(\n      targetMatchers.isSpawnSupply,\n      targetMatchers.needsEnergy,\n    ),\n  });\n  if (targets.length) {\n    const target = creep.pos.findClosestByRange(targets);\n    const range = creep.pos.getRangeTo(target);\n    if (range \u003e 1) {\n      creep.routeTo(target, { range: 1 });\n    } else {\n      const amount = Math.min(creep.carry[RESOURCE_ENERGY], target.energyCapacity - target.energy);\n      creep.transfer(target, RESOURCE_ENERGY, amount);\n      delete creep.memory.target;\n    }\n  } else {\n    yield done({\n      noTarget: true,\n    });\n  }\n}\n\nexport function* harvest(creep, {\n  priority,\n  sleep,\n  done,\n  context,\n}) {\n  yield priority();\n  if (_.sum(creep.carry) === creep.carryCapacity) {\n    delete creep.memory.target;\n    return yield done();\n  }\n  let target;\n  if (!context.sourceId) {\n    context.sourceId = getSourceId(creep);\n  }\n  if (context.sourceId) {\n    target = Game.getObjectById(context.sourceId);\n  }\n  if (target) {\n    const range = creep.pos.getRangeTo(target);\n    if (range \u003e 1) {\n      creep.routeTo(target, { range: 1 });\n    } else {\n      creep.memory.target = target.id;\n      creep.harvest(target);\n    }\n  }\n}\n\nexport function* upgradeController(creep, {\n  priority,\n  done,\n  context,\n}) {\n  yield priority();\n  if (_.sum(creep.carry) === 0) {\n    delete creep.memory.target;\n    delete creep.memory.range;\n    yield done();\n  }\n  const target = creep.room.controller;\n  if (!target) {\n    yield done({\n      noTarget: true,\n    });\n  }\n  const range = creep.pos.getRangeTo(target);\n  if (range \u003e 3) {\n    creep.routeTo(target, { range: 3 });\n  } else {\n    creep.memory.target = target.id;\n    creep.memory.range = 3;\n    creep.upgradeController(target);\n  }\n}\n\n```\n\n### Sub task\n\nTasks can be composed into higher level tasks using `subTask`. Subtasks can return results when the call `done` which can be used to perform additional logic.\n\nExample:\n\n```\nexport function* pioneer(creep, {\n  priority,\n  subTask,\n  context,\n}) {\n  yield priority();\n  if (_.sum(creep.carry) === creep.carryCapacity) {\n    let results = yield subTask(supplySpawn);\n    if (results.noTarget) {\n      results = yield subTask(construct);\n      if (results.noTarget) {\n        yield subTask(upgradeController);\n      }\n    }\n  } else {\n    return yield subTask(harvest);\n  }\n}\n```\n\n`subTask` creates a child task to a parent task. The child task will run until that task calls `done` at which point the parent task will regain control.\n\n### Priority or sleep\n\nAll tasks must first yield a priority or a sleep before any other yield. This is used to determine the priority of the task in relation to every other task the creep is assigned. Priorities are in ascending order, so `-Infinity` is the highest priority and `Infinity` is the lowest priority. An `undefined` priority is assumed to be 0.\n\nYielding sleep will inform the task manager that there is nothing to do for the task. The task will not be considered for priority but also will stay active, for example in the case of a subtask. If you want to sleep for a specific amount of ticks, then `yield sleep(ticks);`\n\n### Context\n\nTasks can save state to their `context` which is saved to the game object's memory and is associated with the task. Context is destroyed when the task is destroyed so save directly to memory if data needs to be saved past the task lifetime.\n\nContext is shared with sub tasks. For example:\n\n```\nexport function* master(creep, {\n  priority,\n  subTask,\n}) {\n  yield priority();\n  context.foo = 'bar';\n  yield subTask(slave);\n}\n\nexport function* slave(creep, {\n  priority,\n  done,\n}) {\n  yield priority();\n  assert(context.foo === 'bar'); // true\n  yield done();\n}\n```\n\nContext of a task or a sub task can also be defined when they are created:\n\n```\nexport function* master(creep, {\n  priority,\n  subTask,\n}) {\n  yield priority();\n  yield subTask(slave, {\n    foo: 'bar',\n  });\n}\n\nexport function* slave(creep, {\n  priority,\n  done,\n}) {\n  yield priority();\n  assert(context.foo === 'bar'); // true\n  yield done();\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaptemulation%2Fscreeps-redux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaptemulation%2Fscreeps-redux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaptemulation%2Fscreeps-redux/lists"}