aaaaaaaaaaaaaaaaa??!

This commit is contained in:
jane 2023-10-29 22:50:29 -04:00
commit 302ac37756
24 changed files with 1337 additions and 0 deletions

11
.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
/bower_components/
/node_modules/
/.pulp-cache/
/output/
/generated-docs/
/.psc-package/
/.psc*
/.purs*
/.psa*
/.spago
index.js

109
packages.dhall Normal file
View file

@ -0,0 +1,109 @@
{-
Welcome to your new Dhall package-set!
Below are instructions for how to edit this file for most use
cases, so that you don't need to know Dhall to use it.
## Use Cases
Most will want to do one or both of these options:
1. Override/Patch a package's dependency
2. Add a package not already in the default package set
This file will continue to work whether you use one or both options.
Instructions for each option are explained below.
### Overriding/Patching a package
Purpose:
- Change a package's dependency to a newer/older release than the
default package set's release
- Use your own modified version of some dependency that may
include new API, changed API, removed API by
using your custom git repo of the library rather than
the package set's repo
Syntax:
where `entityName` is one of the following:
- dependencies
- repo
- version
-------------------------------
let upstream = --
in upstream
with packageName.entityName = "new value"
-------------------------------
Example:
-------------------------------
let upstream = --
in upstream
with halogen.version = "master"
with halogen.repo = "https://example.com/path/to/git/repo.git"
with halogen-vdom.version = "v4.0.0"
with halogen-vdom.dependencies = [ "extra-dependency" ] # halogen-vdom.dependencies
-------------------------------
### Additions
Purpose:
- Add packages that aren't already included in the default package set
Syntax:
where `<version>` is:
- a tag (i.e. "v4.0.0")
- a branch (i.e. "master")
- commit hash (i.e. "701f3e44aafb1a6459281714858fadf2c4c2a977")
-------------------------------
let upstream = --
in upstream
with new-package-name =
{ dependencies =
[ "dependency1"
, "dependency2"
]
, repo =
"https://example.com/path/to/git/repo.git"
, version =
"<version>"
}
-------------------------------
Example:
-------------------------------
let upstream = --
in upstream
with benchotron =
{ dependencies =
[ "arrays"
, "exists"
, "profunctor"
, "strings"
, "quickcheck"
, "lcg"
, "transformers"
, "foldable-traversable"
, "exceptions"
, "node-fs"
, "node-buffer"
, "node-readline"
, "datetime"
, "now"
]
, repo =
"https://github.com/hdgarrood/purescript-benchotron.git"
, version =
"v7.0.0"
}
-------------------------------
-}
let upstream =
https://github.com/purescript/package-sets/releases/download/psc-0.15.12-20231024/packages.dhall
sha256:8aa63621af6a0e6d8d4611279b454a1a69364be9f1151530aca72432160fa439
let overrides = {=}
let additions = {=}
in upstream // overrides // additions

35
spago.dhall Normal file
View file

@ -0,0 +1,35 @@
{-
Welcome to a Spago project!
You can edit this file as you like.
Need help? See the following resources:
- Spago documentation: https://github.com/purescript/spago
- Dhall language tour: https://docs.dhall-lang.org/tutorials/Language-Tour.html
When creating a new Spago project, you can use
`spago init --no-comments` or `spago init -C`
to generate this file without the comments in this block.
-}
{ name = "ps-screeps-bot"
, dependencies =
[ "argonaut-codecs"
, "argonaut-core"
, "argonaut-generic"
, "arrays"
, "console"
, "effect"
, "either"
, "foldable-traversable"
, "foreign-object"
, "functions"
, "integers"
, "lists"
, "maybe"
, "ordered-collections"
, "partial"
, "prelude"
, "tuples"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}

58
src/Main.purs Normal file
View file

@ -0,0 +1,58 @@
module Main where
import Prelude
import Screeps.Types
import Data.Argonaut.Decode (printJsonDecodeError)
import Data.Either (Either(..))
import Data.Int (decimal, toStringAs)
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)
import Screeps.Game as Game
import Screeps.Memory as Memory
import Shimmy.Creep (manageCreeps)
import Shimmy.Spawning (initSpawn)
main :: Effect Unit
main = do
game <- Game.getGameGlobal
memory <- Memory.getMemoryGlobal
status <- isInitialized memory
case status of
Nothing -> do
initLoop game memory LoopGo
Just s -> do
runLoop game memory s
-- | is initialized
isInitialized :: Memory.MemoryGlobal -> Effect (Maybe LoopStatus)
isInitialized memory = do
status <- Memory.get memory "loopStatus"
case status of
Left err -> do
log $ printJsonDecodeError err
pure Nothing
Right s -> case s of
Nothing -> pure $ Just LoopGo
Just s1 -> pure s1
-- | init loop
initLoop :: GameGlobal -> Memory.MemoryGlobal -> LoopStatus -> Effect Unit
initLoop game memory status = do
log "init loop"
Memory.set memory "loopStatus" $ Just status
Memory.set memory "utility" 0
let creeps = Game.creeps game
initSpawn creeps game memory
manageCreeps creeps game memory
--
-- | run loop
runLoop :: GameGlobal -> Memory.MemoryGlobal -> LoopStatus -> Effect Unit
runLoop game memory status = do
let creeps = Game.creeps game
time = Game.time game
log $ toStringAs decimal time
manageCreeps creeps game memory

117
src/Screeps/Const.js Normal file
View file

@ -0,0 +1,117 @@
"use_strict";
export const ok = OK;
export const err_not_owner = ERR_NOT_OWNER;
export const err_no_path = ERR_NO_PATH;
export const err_name_exists = ERR_NAME_EXISTS;
export const err_busy = ERR_BUSY;
export const err_not_found = ERR_NOT_FOUND;
export const err_not_enough_energy = ERR_NOT_ENOUGH_ENERGY;
export const err_not_enough_resources = ERR_NOT_ENOUGH_RESOURCES;
export const err_invalid_target = ERR_INVALID_TARGET;
export const err_full = ERR_FULL;
export const err_not_in_range = ERR_NOT_IN_RANGE;
export const err_invalid_args = ERR_INVALID_ARGS;
export const err_tired = ERR_TIRED;
export const err_no_bodypart = ERR_NO_BODYPART;
export const err_not_enough_extensions = ERR_NOT_ENOUGH_EXTENSIONS;
export const err_rcl_not_enough = ERR_RCL_NOT_ENOUGH;
export const err_gcl_not_enough = ERR_GCL_NOT_ENOUGH;
export const find_exit_top = FIND_EXIT_TOP;
export const find_exit_right = FIND_EXIT_RIGHT;
export const find_exit_bottom = FIND_EXIT_BOTTOM;
export const find_exit_left = FIND_EXIT_LEFT;
export const find_exit = FIND_EXIT;
export const find_creeps = FIND_CREEPS;
export const find_my_creeps = FIND_MY_CREEPS;
export const find_hostile_creeps = FIND_HOSTILE_CREEPS;
export const find_sources_active = FIND_SOURCES_ACTIVE;
export const find_sources = FIND_SOURCES;
export const find_dropped_energy = FIND_DROPPED_ENERGY;
export const find_dropped_resources = FIND_DROPPED_RESOURCES;
export const find_structures = FIND_STRUCTURES;
export const find_structures0 = FIND_STRUCTURES;
export const find_my_structures = FIND_MY_STRUCTURES;
export const find_hostile_structures = FIND_HOSTILE_STRUCTURES;
export const find_flags = FIND_FLAGS;
export const find_construction_sites = FIND_CONSTRUCTION_SITES;
export const find_my_spawns = FIND_MY_SPAWNS;
export const find_hostile_spawns = FIND_HOSTILE_SPAWNS;
export const find_my_construction_sites = FIND_MY_CONSTRUCTION_SITES;
export const find_hostile_construction_sites = FIND_HOSTILE_CONSTRUCTION_SITES;
export const find_minerals = FIND_MINERALS;
export const find_nukes = FIND_NUKES;
export const structure_spawn = STRUCTURE_SPAWN;
export const structure_extension = STRUCTURE_EXTENSION;
export const structure_road = STRUCTURE_ROAD;
export const structure_wall = STRUCTURE_WALL;
export const structure_rampart = STRUCTURE_RAMPART;
export const structure_keeper_lair = STRUCTURE_KEEPER_LAIR;
export const structure_portal = STRUCTURE_PORTAL;
export const structure_controller = STRUCTURE_CONTROLLER;
export const structure_link = STRUCTURE_LINK;
export const structure_storage = STRUCTURE_STORAGE;
export const structure_tower = STRUCTURE_TOWER;
export const structure_observer = STRUCTURE_OBSERVER;
export const structure_power_bank = STRUCTURE_POWER_BANK;
export const structure_power_spawn = STRUCTURE_POWER_SPAWN;
export const structure_extractor = STRUCTURE_EXTRACTOR;
export const structure_lab = STRUCTURE_LAB;
export const structure_terminal = STRUCTURE_TERMINAL;
export const structure_container = STRUCTURE_CONTAINER;
export const structure_nuker = STRUCTURE_NUKER;
export const pMove = MOVE;
export const pWork = WORK;
export const pCarry = CARRY;
export const resource_energy = RESOURCE_ENERGY;
export const resource_power = RESOURCE_POWER;
export const resource_hydrogen = RESOURCE_HYDROGEN;
export const resource_oxygen = RESOURCE_OXYGEN;
export const resource_utrium = RESOURCE_UTRIUM;
export const resource_lemergium = RESOURCE_LEMERGIUM;
export const resource_keanium = RESOURCE_KEANIUM;
export const resource_zynthium = RESOURCE_ZYNTHIUM;
export const resource_catalyst = RESOURCE_CATALYST;
export const resource_ghodium = RESOURCE_GHODIUM;
export const resource_hydroxide = RESOURCE_HYDROXIDE;
export const resource_zynthium_keanite = RESOURCE_ZYNTHIUM_KEANITE;
export const resource_utrium_lemergite = RESOURCE_UTRIUM_LEMERGITE;
export const resource_utrium_hydride = RESOURCE_UTRIUM_HYDRIDE;
export const resource_utrium_oxide = RESOURCE_UTRIUM_OXIDE;
export const resource_keanium_hydride = RESOURCE_KEANIUM_HYDRIDE;
export const resource_keanium_oxide = RESOURCE_KEANIUM_OXIDE;
export const resource_lemergium_hydride = RESOURCE_LEMERGIUM_HYDRIDE;
export const resource_lemergium_oxide = RESOURCE_LEMERGIUM_OXIDE;
export const resource_zynthium_hydride = RESOURCE_ZYNTHIUM_HYDRIDE;
export const resource_zynthium_oxide = RESOURCE_ZYNTHIUM_OXIDE;
export const resource_ghodium_hydride = RESOURCE_GHODIUM_HYDRIDE;
export const resource_ghodium_oxide = RESOURCE_GHODIUM_OXIDE;
export const resource_utrium_acid = RESOURCE_UTRIUM_ACID;
export const resource_utrium_alkalide = RESOURCE_UTRIUM_ALKALIDE;
export const resource_keanium_acid = RESOURCE_KEANIUM_ACID;
export const resource_keanium_alkalide = RESOURCE_KEANIUM_ALKALIDE;
export const resource_lemergium_acid = RESOURCE_LEMERGIUM_ACID;
export const resource_lemergium_alkalide = RESOURCE_LEMERGIUM_ALKALIDE;
export const resource_zynthium_acid = RESOURCE_ZYNTHIUM_ACID;
export const resource_zynthium_alkalide = RESOURCE_ZYNTHIUM_ALKALIDE;
export const resource_ghodium_acid = RESOURCE_GHODIUM_ACID;
export const resource_ghodium_alkalide = RESOURCE_GHODIUM_ALKALIDE;
export const resource_catalyzed_utrium_acid = RESOURCE_CATALYZED_UTRIUM_ACID;
export const resource_catalyzed_utrium_alkalide = RESOURCE_CATALYZED_UTRIUM_ALKALIDE;
export const resource_catalyzed_keanium_acid = RESOURCE_CATALYZED_KEANIUM_ACID;
export const resource_catalyzed_keanium_alkalide = RESOURCE_CATALYZED_KEANIUM_ALKALIDE;
export const resource_catalyzed_lemergium_acid = RESOURCE_CATALYZED_LEMERGIUM_ACID;
export const resource_catalyzed_lemergium_alkalide = RESOURCE_CATALYZED_LEMERGIUM_ALKALIDE;
export const resource_catalyzed_zynthium_acid = RESOURCE_CATALYZED_ZYNTHIUM_ACID;
export const resource_catalyzed_zynthium_alkalide = RESOURCE_CATALYZED_ZYNTHIUM_ALKALIDE;
export const resource_catalyzed_ghodium_acid = RESOURCE_CATALYZED_GHODIUM_ACID;
export const resource_catalyzed_ghodium_alkalide = RESOURCE_CATALYZED_GHODIUM_ALKALIDE;

118
src/Screeps/Const.purs Normal file
View file

@ -0,0 +1,118 @@
module Screeps.Const where
import Prelude
import Screeps.Types
foreign import ok :: ReturnCode
foreign import err_not_owner :: ReturnCode
foreign import err_no_path :: ReturnCode
foreign import err_name_exists :: ReturnCode
foreign import err_busy :: ReturnCode
foreign import err_not_found :: ReturnCode
foreign import err_not_enough_energy :: ReturnCode
foreign import err_not_enough_resources :: ReturnCode
foreign import err_invalid_target :: ReturnCode
foreign import err_full :: ReturnCode
foreign import err_not_in_range :: ReturnCode
foreign import err_invalid_args :: ReturnCode
foreign import err_tired :: ReturnCode
foreign import err_no_bodypart :: ReturnCode
foreign import err_not_enough_extensions :: ReturnCode
foreign import err_rcl_not_enough :: ReturnCode
foreign import err_gcl_not_enough :: ReturnCode
foreign import pMove :: BodyPartType
foreign import pWork :: BodyPartType
foreign import pCarry :: BodyPartType
foreign import find_exit_top :: FindType RoomPosition
foreign import find_exit_right :: FindType RoomPosition
foreign import find_exit_bottom :: FindType RoomPosition
foreign import find_exit_left :: FindType RoomPosition
foreign import find_exit :: FindType RoomPosition
foreign import find_creeps :: FindType Creep
foreign import find_my_creeps :: FindType Creep
foreign import find_hostile_creeps :: FindType Creep
foreign import find_sources_active :: FindType Source
foreign import find_sources :: FindType Source
foreign import find_dropped_energy :: FindType Resource
foreign import find_dropped_resources :: FindType Resource
foreign import find_structures :: FindType (Structure Unit)
foreign import find_my_structures :: forall a. FindType (Structure a)
foreign import find_hostile_structures :: FindType (Structure Unit)
foreign import find_flags :: FindType Flag
foreign import find_construction_sites :: FindType ConstructionSite
foreign import find_my_spawns :: FindType Spawn
foreign import find_hostile_spawns :: FindType Spawn
foreign import find_my_construction_sites :: FindType ConstructionSite
foreign import find_hostile_construction_sites :: FindType ConstructionSite
foreign import find_minerals :: FindType Mineral
foreign import find_nukes :: FindType Nuke
foreign import structure_spawn :: StructureType
foreign import structure_extension :: StructureType
foreign import structure_road :: StructureType
foreign import structure_wall :: StructureType
foreign import structure_rampart :: StructureType
foreign import structure_keeper_lair :: StructureType
foreign import structure_portal :: StructureType
foreign import structure_controller :: StructureType
foreign import structure_link :: StructureType
foreign import structure_storage :: StructureType
foreign import structure_tower :: StructureType
foreign import structure_observer :: StructureType
foreign import structure_power_bank :: StructureType
foreign import structure_power_spawn :: StructureType
foreign import structure_extractor :: StructureType
foreign import structure_lab :: StructureType
foreign import structure_terminal :: StructureType
foreign import structure_container :: StructureType
foreign import structure_nuker :: StructureType
foreign import resource_energy :: ResourceType
foreign import resource_power :: ResourceType
foreign import resource_hydrogen :: ResourceType
foreign import resource_oxygen :: ResourceType
foreign import resource_utrium :: ResourceType
foreign import resource_lemergium :: ResourceType
foreign import resource_keanium :: ResourceType
foreign import resource_zynthium :: ResourceType
foreign import resource_catalyst :: ResourceType
foreign import resource_ghodium :: ResourceType
foreign import resource_hydroxide :: ResourceType
foreign import resource_zynthium_keanite :: ResourceType
foreign import resource_utrium_lemergite :: ResourceType
foreign import resource_utrium_hydride :: ResourceType
foreign import resource_utrium_oxide :: ResourceType
foreign import resource_keanium_hydride :: ResourceType
foreign import resource_keanium_oxide :: ResourceType
foreign import resource_lemergium_hydride :: ResourceType
foreign import resource_lemergium_oxide :: ResourceType
foreign import resource_zynthium_hydride :: ResourceType
foreign import resource_zynthium_oxide :: ResourceType
foreign import resource_ghodium_hydride :: ResourceType
foreign import resource_ghodium_oxide :: ResourceType
foreign import resource_utrium_acid :: ResourceType
foreign import resource_utrium_alkalide :: ResourceType
foreign import resource_keanium_acid :: ResourceType
foreign import resource_keanium_alkalide :: ResourceType
foreign import resource_lemergium_acid :: ResourceType
foreign import resource_lemergium_alkalide :: ResourceType
foreign import resource_zynthium_acid :: ResourceType
foreign import resource_zynthium_alkalide :: ResourceType
foreign import resource_ghodium_acid :: ResourceType
foreign import resource_ghodium_alkalide :: ResourceType
foreign import resource_catalyzed_utrium_acid :: ResourceType
foreign import resource_catalyzed_utrium_alkalide :: ResourceType
foreign import resource_catalyzed_keanium_acid :: ResourceType
foreign import resource_catalyzed_keanium_alkalide :: ResourceType
foreign import resource_catalyzed_lemergium_acid :: ResourceType
foreign import resource_catalyzed_lemergium_alkalide :: ResourceType
foreign import resource_catalyzed_zynthium_acid :: ResourceType
foreign import resource_catalyzed_zynthium_alkalide :: ResourceType
foreign import resource_catalyzed_ghodium_acid :: ResourceType
foreign import resource_catalyzed_ghodium_alkalide :: ResourceType

4
src/Screeps/Creep.js Normal file
View file

@ -0,0 +1,4 @@
"use strict";
export function totalAmtCarrying(creep){
return _.sum(creep.carry);
}

133
src/Screeps/Creep.purs Normal file
View file

@ -0,0 +1,133 @@
module Screeps.Creep where
import Prelude
import Effect (Effect)
import Data.Maybe (Maybe)
import Data.Either (Either)
import Data.Argonaut.Decode (class DecodeJson, decodeJson, JsonDecodeError)
import Data.Argonaut.Encode (class EncodeJson, encodeJson)
import Screeps.FFI (unsafeGetCreepEff)
import Screeps.Types
import Screeps.FFI ( unsafeField, runThisFn1
, runThisEffFn1, runThisEffFn2
, runThisEffFn3, toMaybe
, unsafeGetCreepEff, unsafeSetCreepEff
, unsafeGetAllCreepEff )
foreign import data CreepCargo :: Type
foreign import totalAmtCarrying :: Creep -> Int
body :: Creep -> Array BodyPart
body creep = unsafeField "body" creep
carry :: Creep -> CreepCargo
carry = unsafeField "carry"
amtCarrying :: Creep -> ResourceType -> Int
amtCarrying creep res = unsafeField (show res) $ carry creep
carryCapacity :: Creep -> Int
carryCapacity = unsafeField "carryCapacity"
fatigue :: Creep -> Int
fatigue = unsafeField "fatigue"
hits :: Creep -> Int
hits = unsafeField "hits"
hitsMax :: Creep -> Int
hitsMax = unsafeField "hitsMax"
getId :: Creep -> Id Creep
getId = unsafeField "id"
getIdAsStr :: Creep -> String
getIdAsStr = unsafeField "id"
my :: Creep -> Boolean
my = unsafeField "my"
name :: Creep -> String
name = unsafeField "name"
owner :: Creep -> { username :: String }
owner = unsafeField "owner"
saying :: Creep -> Maybe String
saying c = toMaybe $ unsafeField "saying" c
spawning :: Creep -> Boolean
spawning = unsafeField "spawning"
ticksToLive :: Creep -> Int
ticksToLive = unsafeField "ticksToLive"
attackCreep :: Creep -> Creep -> Effect ReturnCode
attackCreep = runThisEffFn1 "attack"
attackStructure :: forall a. Creep → Structure a -> Effect ReturnCode
attackStructure = runThisEffFn1 "attack"
attackController :: forall a. Creep -> Structure a -> Effect ReturnCode
attackController = runThisEffFn1 "attackController"
build :: Creep -> ConstructionSite -> Effect ReturnCode
build = runThisEffFn1 "build"
cancelOrder :: Creep -> String -> Effect ReturnCode
cancelOrder = runThisEffFn1 "cancelOrder"
claimController :: forall a. Creep -> Structure a -> Effect ReturnCode
claimController = runThisEffFn1 "claimController"
dismantle :: forall a. Creep -> Structure a -> Effect ReturnCode
dismantle = runThisEffFn1 "dismantle"
drop :: Creep -> ResourceType -> Effect ReturnCode
drop = runThisEffFn1 "drop"
dropAmt :: Creep -> ResourceType -> Int -> Effect ReturnCode
dropAmt = runThisEffFn2 "drop"
getActiveBodyparts :: Creep -> BodyPartType -> Int
getActiveBodyparts = runThisFn1 "getActiveBodyparts"
harvestSource :: Creep -> Source -> Effect ReturnCode
harvestSource = runThisEffFn1 "harvest"
harvestMineral :: Creep -> Mineral -> Effect ReturnCode
harvestMineral = runThisEffFn1 "harvest"
heal :: Creep -> Creep -> Effect ReturnCode
heal = runThisEffFn1 "heal"
move :: Creep -> Direction -> Effect ReturnCode
move = runThisEffFn1 "move"
moveByPath :: Creep -> Path -> Effect ReturnCode
moveByPath = runThisEffFn1 "moveByPath"
moveTo :: forall a. Creep -> TargetPosition a -> Effect ReturnCode
moveTo creep (TargetPt x y) = runThisEffFn2 "moveTo" creep x y
moveTo creep (TargetPos pos) = runThisEffFn1 "moveTo" creep pos
moveTo creep (TargetObj obj) = runThisEffFn1 "moveTo" creep obj
transferToCreep :: Creep -> Creep -> ResourceType -> Int -> Effect ReturnCode
transferToCreep = runThisEffFn3 "transfer"
transferToStructure :: forall a. Creep -> Structure a -> ResourceType -> Effect ReturnCode
transferToStructure = runThisEffFn2 "transfer"
transferAmtToStructure :: forall a. Creep -> Structure a -> ResourceType -> Int -> Effect ReturnCode
transferAmtToStructure = runThisEffFn3 "transfer"
creepStore ∷ Creep → Store
creepStore = unsafeField "store"
getAllCreepMem ∷ ∀ a. (DecodeJson a) ⇒ String → Effect (Either JsonDecodeError a)
getAllCreepMem creep = decodeJson <$> unsafeGetAllCreepEff creep
getCreepMem ∷ ∀ a. (DecodeJson a) ⇒ String → String → Effect (Either JsonDecodeError a)
getCreepMem creep key = decodeJson <$> unsafeGetCreepEff creep key
setCreepMem ∷ ∀ a. (EncodeJson a) ⇒ String → String → a → Effect Unit
setCreepMem creep key val = unsafeSetCreepEff creep key $ encodeJson val

166
src/Screeps/FFI.js Normal file
View file

@ -0,0 +1,166 @@
"use strict";
// module Screeps.FFI
export function unsafeField(key){
return function(obj){
return obj[key];
}
}
export function unsafeGetFieldEff(key){
return function(obj){
return function(){
return obj[key];
}
}
}
export function unsafeSetFieldEff(key){
return function(obj){
return function(val){
return function(){
obj[key] = val;
}
}
}
}
export function unsafeDeleteFieldEff(key){
return function(obj){
return function(){
delete obj[key];
}
}
}
export function runThisEffFn0(key){
return function(self){
return function(){
return self[key]();
}
}
}
export function runThisEffFn1(key){
return function(self){
return function(a){
return function(){
return self[key](a);
}
}
}
}
export function runThisEffFn2(key){
return function(self){
return function(a){
return function(b){
return function(){
return self[key](a, b);
}
}
}
}
}
export function runThisEffFn3(key){
return function(self){
return function(a){
return function(b){
return function(c){
return function(){
return self[key](a, b, c);
}
}
}
}
}
}
export function runThisEffFn4(key){
return function(self){
return function(a){
return function(b){
return function(c){
return function(d){
return function(){
return self[key](a, b, c, d);
}
}
}
}
}
}
}
export function runThisFn0(key){
return function(self){
return self[key]();
}
}
export function runThisFn1(key){
return function(self){
return function(a){
return self[key](a);
}
}
}
export function runThisFn2(key){
return function(self){
return function(a){
return function(b){
return self[key](a,b);
}
}
}
}
export function runThisFn3(key){
return function(self){
return function(a){
return function(b){
return function(c){
return self[key](a,b,c);
}
}
}
}
}
export const _null = null;
export const _undefined = undefined
export function notNullOrUndefined(x){
return x;
}
export function isNull(x){
return x === null;
}
export function isUndefined(x){
return x === undefined;
}
export function toMaybeImpl (val, nothing, just){
if(val === null || val === undefined){
return nothing;
} else {
return just(val);
}
}
export function unsafeGetAllCreepEff(creep){
return function(){
return Memory.creeps[creep];
}
}
export function unsafeGetCreepEff(creep,key){
return function(){
return Memory.creeps[creep][key];
}
}
export function unsafeSetCreepEff(creep,key){
return function(val){
return Memory.creeps[creep][key] = val;
}
}
// export function rawSpawnCreep(){
// return function (self){
// return function(spawn){
// return function(parts){
// return function(name){
// return function(r){
// console.log("spawning creep...");
// return self.spawns[spawn].spawnCreep(parts,name,{memory: {role: r, utility: 1}});
// }
// }
// }
// }
// }
// }

37
src/Screeps/FFI.purs Normal file
View file

@ -0,0 +1,37 @@
module Screeps.FFI where
import Prelude
import Effect (Effect)
import Data.Maybe (Maybe(Just, Nothing), isJust, fromJust, maybe)
import Data.Function.Uncurried ( Fn3, runFn3 )
import Screeps.Types
foreign import unsafeField :: forall obj val. String -> obj -> val
foreign import unsafeGetFieldEff :: forall obj val. String -> obj -> Effect val
foreign import unsafeSetFieldEff :: forall obj val. String -> obj -> val -> Effect Unit
foreign import unsafeDeleteFieldEff :: forall obj. String -> obj -> Effect Unit
foreign import runThisEffFn0 :: forall this a. String -> this -> Effect a
foreign import runThisEffFn1 :: forall this a b. String -> this -> a -> Effect b
foreign import runThisEffFn2 :: forall this a b c. String -> this -> a -> b -> Effect c
foreign import runThisEffFn3 :: forall this a b c d. String
-> this -> a -> b -> c -> Effect d
foreign import runThisEffFn4 :: forall this a b c d e. String
-> this -> a -> b -> c -> d -> Effect e
foreign import runThisFn0 :: forall this a. String -> this -> a
foreign import runThisFn1 :: forall this a b. String -> this -> a -> b
foreign import runThisFn2 :: forall this a b c. String -> this -> a -> b → c
foreign import runThisFn3 :: forall this a b c d. String -> this -> a -> b → c → d
foreign import data NullOrUndefined :: Type -> Type
foreign import _null :: forall a. NullOrUndefined a
foreign import _undefined :: forall a. NullOrUndefined a
foreign import notNullOrUndefined :: forall a. a -> NullOrUndefined a
foreign import isNull :: forall a. NullOrUndefined a -> Boolean
foreign import isUndefined :: forall a. NullOrUndefined a -> Boolean
foreign import toMaybeImpl :: forall a m. Fn3 (NullOrUndefined a) m (a -> m) m
foreign import unsafeGetAllCreepEff :: ∀ val. String → Effect val
foreign import unsafeGetCreepEff :: ∀ val. String → String → Effect val
foreign import unsafeSetCreepEff :: ∀ val. String → String → val → Effect Unit
toMaybe :: forall a. NullOrUndefined a -> Maybe a
toMaybe n = runFn3 toMaybeImpl n Nothing Just

32
src/Screeps/Game.js Normal file
View file

@ -0,0 +1,32 @@
"use strict";
export function getGameGlobal(){ return Game; }
export function createCreepImpl(structure){
return function(parts){
return function(role){
return function(left){
return function(right){
return function(){
var result = structure.createCreep(parts,{utility: 1, role: role});
if (typeof result === "string"){
return right(result);
} else {
return left(result);
}
}
}
}
}
}
}
export function rawGetUtility(key){
return function(obj){
return obj.creeps[key].utility;
}
}
export function rawGetRole(key){
return function(obj){
return obj.creeps[key].role;
}
}

65
src/Screeps/Game.purs Normal file
View file

@ -0,0 +1,65 @@
module Screeps.Game where
import Prelude
import Foreign.Object as F
import Effect (Effect)
import Screeps.Types
import Screeps.Memory as Memory
import Screeps.FFI ( runThisEffFn0, runThisFn1
, unsafeField, toMaybe )
import Data.Maybe ( Maybe )
import Data.Either ( Either(..) )
import Data.Argonaut.Core ( Json )
import Data.Argonaut.Encode ( encodeJson )
import Data.Map as Map
foreign import getGameGlobal ∷ Effect GameGlobal
foreign import createCreepImpl ∷ Spawn → Array BodyPartType → Json
→ (ReturnCode → Either ReturnCode String)
→ (String → Either ReturnCode String)
→ Effect (Either ReturnCode String)
foreign import rawGetUtility ∷ String → Memory.MemoryGlobal → Int
foreign import rawGetRole ∷ String → Memory.MemoryGlobal → Role
type Cpu = { limit ∷ Int
, tickLimit ∷ Int
, bucket ∷ Int }
cpu ∷ GameGlobal → Cpu
cpu = unsafeField "cpu"
spawns ∷ GameGlobal → F.Object Spawn
spawns = unsafeField "spawns"
creeps ∷ GameGlobal → F.Object Creep
creeps = unsafeField "creeps"
getUsed ∷ GameGlobal → Effect Number
getUsed game = runThisEffFn0 "getUsed" (cpu game)
getObjectById ∷ ∀ a. GameGlobal → Id a → Maybe a
getObjectById game id
= toMaybe (runThisFn1 "getObjectById" game id)
getUtility ∷ Memory.MemoryGlobal → String → Int
getUtility mem key = rawGetUtility key mem
getRole ∷ Memory.MemoryGlobal → String → Role
getRole mem key = rawGetRole key mem
rawSpawnCreep ∷ Spawn → Array BodyPartType → String
→ Role → Effect (Either ReturnCode String)
rawSpawnCreep spawn parts name role
= createCreepImpl spawn parts role' Left Right
where role' = encodeJson role
rawSpawnCreepAs ∷ Spawn
→ Array BodyPartType → String → Role
→ Effect (Either ReturnCode String)
rawSpawnCreepAs spawn parts name role
= createCreepImpl spawn parts role' Left Right
where role' = encodeJson role
time ∷ GameGlobal → Int
time = unsafeField "time"
map ∷ GameGlobal → WorldMap
map = unsafeField "map"

21
src/Screeps/Memory.js Normal file
View file

@ -0,0 +1,21 @@
"use strict";
export function getMemoryGlobal(){ return Memory; }
export function getRawMemoryGlobal(){ return RawMemory; }
export function getCreepsUtl(){
var res = []
for (var c in Memory.creeps) {
res = res.concat(Memory.creeps[c]["utility"])
}
return res
}
export function getCreepsNames(){
var res = []
for (var c in Memory.creeps) {
res += c
}
return res
}
export function setCreepsUtl(key,n){
return Memory.creeps[key] = n
}

22
src/Screeps/Memory.purs Normal file
View file

@ -0,0 +1,22 @@
module Screeps.Memory where
import Prelude
import Effect (Effect)
import Screeps.FFI (unsafeGetFieldEff, unsafeSetFieldEff)
import Data.Tuple (Tuple)
import Data.Argonaut.Core ( Json )
import Data.Argonaut.Decode (class DecodeJson, decodeJson, JsonDecodeError)
import Data.Argonaut.Encode (class EncodeJson, encodeJson)
import Data.Either (Either)
import Foreign.Object as F
foreign import data MemoryGlobal :: Type
foreign import getMemoryGlobal :: Effect MemoryGlobal
foreign import data RawMemoryGlobal :: Type
foreign import getRawMemoryGlobal :: Effect RawMemoryGlobal
foreign import setCreepsUtl :: String -> Int -> Effect Unit
foreign import getCreepsUtl :: Effect (Array Int)
set :: forall a. (EncodeJson a) => MemoryGlobal -> String -> a -> Effect Unit
set memoryGlobal key val = unsafeSetFieldEff key memoryGlobal $ encodeJson val
get :: forall a. (DecodeJson a) => MemoryGlobal -> String -> Effect (Either JsonDecodeError a)
get memoryGlobal key = decodeJson <$> unsafeGetFieldEff key memoryGlobal

5
src/Screeps/Room.js Normal file
View file

@ -0,0 +1,5 @@
"use strict";
export function setRoomMem(room,nharvs,maxnharvs){
return room.memory = { "nharvs" : nharvs, "maxnharvs" : maxnharvs };
}

36
src/Screeps/Room.purs Normal file
View file

@ -0,0 +1,36 @@
module Screeps.Room where
import Prelude
import Effect (Effect)
import Data.Maybe ( Maybe )
import Screeps.Structure ( structureType )
import Screeps.Game as Game
import Screeps.Types
import Screeps.FFI ( runThisFn0, runThisFn1
, runThisFn2, runThisFn3
, unsafeField, toMaybe )
import Foreign.Object as F
-- | returns a list of sources given a room
--findSources ∷ ∀ a. Room → Array (RoomObject a)
--findSources room = find' room find_structures (\s → isSource s)
foreign import setRoomMem :: Room → Int → Int → Effect Unit
find ∷ ∀ a. Room → FindType a → Array a
find = runThisFn1 "find"
-- | returns find when we want to use optional filter
find' ∷ ∀ a. Room → FindType a → FilterFn a → Array a
find' room findType filter = runThisFn2 "find" room findType { filter }
room ∷ ∀ a. RoomObject a → Room
room = unsafeField "room"
storage ∷ Room → Storage
storage = unsafeField "storage"
getTerrain ∷ Room → Terrain
getTerrain = runThisFn0 "getTerrain"
getTerrainAt ∷ ∀ a. TargetPosition a → String → Terrain
getTerrainAt (TargetPt x y) roomName = runThisFn3 "getTerrainAt" Game.map x y roomName
getTerrainAt (TargetPos pos) roomName = runThisFn2 "getTerrainAt" Game.map pos roomName
getTerrainAt (TargetObj obj) roomName = runThisFn2 "getTerrainAt" Game.map obj roomName

12
src/Screeps/Spawn.js Normal file
View file

@ -0,0 +1,12 @@
"use strict";
export function spawnStoreCapacity(obj){
var ret = obj.store;
if (typeof ret !== 'undefined')
return ret.getFreeCapacity(RESOURCE_ENERGY);
}
export function spawnStoreEnergy(obj){
var ret = obj.store;
if (typeof ret !== 'undefined')
return ret[RESOURCE_ENERGY];
}

13
src/Screeps/Spawn.purs Normal file
View file

@ -0,0 +1,13 @@
module Screeps.Spawn where
import Prelude
import Effect (Effect)
import Screeps.Types
import Screeps.FFI ( unsafeField, toMaybe )
import Data.Maybe (Maybe)
foreign import spawnStoreCapacity ∷ ∀ obj. obj → Int
foreign import spawnStoreEnergy ∷ ∀ obj. obj → Int
spawnStore ∷ ∀ a. Structure a → Store
spawnStore = unsafeField "store"

19
src/Screeps/Storage.purs Normal file
View file

@ -0,0 +1,19 @@
module Screeps.Storage where
import Prelude
import Screeps.Types
import Screeps.FFI (unsafeField,runThisFn0)
storeFreeCapacity ∷ Store → Int
storeFreeCapacity = runThisFn0 "getFreeCapacity"
storeCapacity ∷ Store → Int
storeCapacity = unsafeField "storeCapacity"
store ∷ Storage → Store
store = unsafeField "store"
storageGet ∷ Storage → ResourceType → Int
storageGet s (ResourceType res) = unsafeField res (store s)
storeGet ∷ Store → ResourceType → Int
storeGet s (ResourceType res) = unsafeField res s

View file

@ -0,0 +1,8 @@
module Screeps.Structure where
import Prelude
import Effect (Effect)
import Screeps.Types
import Screeps.FFI ( unsafeField )
structureType ∷ ∀ a. Structure a → StructureType
structureType = unsafeField "structureType"

211
src/Screeps/Types.purs Normal file
View file

@ -0,0 +1,211 @@
module Screeps.Types where
import Prelude
import Data.Eq
import Data.Maybe (Maybe(..))
import Data.Either (note)
import Data.Generic.Rep ( class Generic )
import Data.Eq.Generic ( genericEq )
import Data.Show ( class Show )
import Data.Show.Generic ( genericShow )
import Data.Argonaut.Decode (class DecodeJson, decodeJson, JsonDecodeError(..), getField)
import Data.Argonaut.Encode (class EncodeJson, encodeJson)
import Data.Argonaut.Encode.Generic (genericEncodeJson)
import Data.Argonaut.Decode.Generic (genericDecodeJson)
foreign import data GameGlobal :: Type
foreign import data RawRoomObject :: Type -> Type
foreign import data Room :: Type
foreign import data WorldMap :: Type
foreign import data RawStructure :: Type -> Type
foreign import data RawOwnedStructure :: Type -> Type
foreign import data RawConstructionSite :: Type
foreign import data RawSpawn :: Type
foreign import data RawTower :: Type
foreign import data RawCreep :: Type
foreign import data RawMineral :: Type
foreign import data RawResource :: Type
foreign import data RawSource :: Type
foreign import data RawStorage :: Type
foreign import data RawFlag :: Type
foreign import data RawNuke :: Type
foreign import data RoomPosition :: Type
foreign import data Store ∷ Type
type RoomObject a = RawRoomObject a
type Structure a = RoomObject (RawStructure a)
type OwnedStructure a = Structure (RawOwnedStructure a)
type ConstructionSite = RoomObject RawConstructionSite
type Storage = OwnedStructure RawStorage
type Spawn = OwnedStructure RawSpawn
type Tower = OwnedStructure RawTower
type Creep = RoomObject RawCreep
type Mineral = RoomObject RawMineral
type Resource = RoomObject RawResource
type Source = RoomObject RawSource
type Flag = RoomObject RawFlag
type Nuke = RoomObject RawNuke
type Path = Array PathStep
type PathStep =
{ x :: Int
, y :: Int
, dx :: Number
, dy :: Number
, direction :: Direction }
newtype Id a = Id String
derive instance genericId :: Generic (Id a) _
instance eqId :: Eq (Id a) where eq = genericEq
instance showId :: Show (Id a) where show = genericShow
instance decodeJsonId :: DecodeJson (Id a) where decodeJson = genericDecodeJson
instance encodeJsonId :: EncodeJson (Id a) where encodeJson = genericEncodeJson
type BodyPart =
{ boost :: Maybe String
, type :: BodyPartType
, hits :: Int }
type MoveOptions = PathOptions
( reusePath :: Maybe Int
, serializeMemory :: Maybe Boolean
, noPathFinding :: Maybe Boolean )
type PathOptions o =
{ ignoreCreeps :: Maybe Boolean
, ignoreDestructibleStructures :: Maybe Boolean
, ignoreRoads :: Maybe Boolean
, ignore :: Maybe (Array RoomPosition)
, avoid :: Maybe (Array RoomPosition)
, maxOps :: Maybe Int
, heuristicWeight :: Maybe Number
, serialize :: Maybe Boolean
, maxRooms :: Maybe Int
| o }
moveOpts :: MoveOptions
moveOpts =
{ ignoreCreeps: Nothing
, ignoreDestructibleStructures: Nothing
, ignoreRoads: Nothing
, ignore: Nothing
, avoid: Nothing
, maxOps: Nothing
, heuristicWeight: Nothing
, serialize: Nothing
, maxRooms: Nothing
, reusePath: Nothing
, serializeMemory: Nothing
, noPathFinding: Nothing }
pathOpts :: PathOptions ()
pathOpts =
{ ignoreCreeps: Nothing
, ignoreDestructibleStructures: Nothing
, ignoreRoads: Nothing
, ignore: Nothing
, avoid: Nothing
, maxOps: Nothing
, heuristicWeight: Nothing
, serialize: Nothing
, maxRooms: Nothing }
newtype BodyPartType = BodyPartType String
derive instance genericBodyPartType :: Generic BodyPartType _
instance eqBodyPartType :: Eq BodyPartType where eq = genericEq
instance showBodyPartType :: Show BodyPartType where show = genericShow
newtype ResourceType = ResourceType String
derive instance genericResourceType :: Generic ResourceType _
instance eqResourceType :: Eq ResourceType where eq = genericEq
instance showResourceType :: Show ResourceType where
show (ResourceType s) = s
newtype ReturnCode = ReturnCode Int
derive instance genericReturnCode :: Generic ReturnCode _
instance eqReturnCode :: Eq ReturnCode where eq = genericEq
instance showReturnCode :: Show ReturnCode where
show (ReturnCode n) = show n
newtype StructureType = StructureType String
derive instance genericStructureType :: Generic StructureType _
instance eqStructureType :: Eq StructureType where eq = genericEq
instance showStructureType :: Show StructureType where show = genericShow
newtype Direction = Direction Int
derive instance genericDirection :: Generic Direction _
instance eqDirection :: Eq Direction where eq = genericEq
instance showDirection :: Show Direction where show = genericShow
newtype TerrainMask = TerrainMask Int
derive instance genericTerrainMask :: Generic TerrainMask _
instance eqTerrainMask :: Eq TerrainMask where eq = genericEq
instance showTerrainMask :: Show TerrainMask where show = genericShow
newtype Terrain = Terrain String
derive instance genericTerrain :: Generic Terrain _
instance eqTerrain :: Eq Terrain where eq = genericEq
instance showTerrain :: Show Terrain
where show (Terrain s) = s
data TargetPosition a =
TargetPt Int Int |
TargetObj (RoomObject a) |
TargetPos RoomPosition
type FilterFn a = a -> Boolean
newtype FindType a = FindType Int
-- | creep types are generic, irrelevant of job or role
data CreepType = CreepDrone | CreepNULL
-- | creeps can take on many roles, depending on what type they are
data Role = RoleIdle
| RoleHarvester
| RoleBuilder
| RoleNULL
instance showRole ∷ Show Role where
show RoleHarvester = "RoleHarvester"
show RoleBuilder = "RoleBuilder"
show RoleIdle = "RoleIdle"
show RoleNULL = "RoleNULL"
instance eqRoles ∷ Eq Role where
eq RoleNULL RoleNULL = true
eq RoleIdle RoleIdle = true
eq RoleHarvester RoleHarvester = true
eq RoleBuilder RoleBuilder = true
eq _ RoleNULL = false
eq RoleNULL _ = false
eq _ _ = false
roleList = [RoleIdle, RoleHarvester, RoleBuilder, RoleNULL] ∷ Array Role
instance encodeRole :: EncodeJson Role where
encodeJson RoleIdle = encodeJson "RoleIdle"
encodeJson RoleHarvester = encodeJson "RoleHarvester"
encodeJson RoleBuilder = encodeJson "RoleBuilder"
encodeJson RoleNULL = encodeJson "RoleNULL"
instance decodeRole :: DecodeJson Role where
decodeJson json = do
string <- decodeJson json
note (TypeMismatch "Role:") (roleFromStr string)
roleFromStr :: String -> Maybe Role
roleFromStr "RoleHarvester" = Just RoleHarvester
roleFromStr "RoleBuilder" = Just RoleBuilder
roleFromStr "RoleIdle" = Just RoleIdle
roleFromStr "RoleNULL" = Just RoleNULL
roleFromStr _ = Nothing
-- | jobs are like temporary roles
data Job = JobBuild | JobNULL
-- | the main loop control variable allow some control over state
-- encoded straight into the json memory so we write some instances
data LoopStatus = LoopGo | LoopStop | LoopNULL
instance encodeLoopStatus :: EncodeJson LoopStatus where
encodeJson LoopGo = encodeJson "loopGo"
encodeJson LoopStop = encodeJson "loopStop"
encodeJson LoopNULL = encodeJson "loopNULL"
instance decodeLoopStatus :: DecodeJson LoopStatus where
decodeJson json = do
string <- decodeJson json
note (TypeMismatch "LoopStatus:") (lsFromStr string)
lsFromStr :: String -> Maybe LoopStatus
lsFromStr "loopGo" = Just LoopGo
lsFromStr "loopStop" = Just LoopStop
lsFromStr "loopNULL" = Just LoopNULL
lsFromStr _ = Nothing

20
src/Shimmy/Creep.purs Normal file
View file

@ -0,0 +1,20 @@
module Shimmy.Creep where
import Prelude
import Screeps.Types
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Foreign.Object as F
import Screeps.Game as Game
import Screeps.Memory as Memory
import Shimmy.Spawning (doSpawnCheck)
manageCreeps :: F.Object Creep -> GameGlobal -> Memory.MemoryGlobal -> Effect Unit
manageCreeps hash game mem = do
let spawns = Game.spawns game
-- TODO: iterate over all spawns?
spawn1 = F.lookup "Spawn1" spawns
case spawn1 of
Nothing -> pure unit
Just s1 -> doSpawnCheck s1 (F.size hash) mem

74
src/Shimmy/Spawning.purs Normal file
View file

@ -0,0 +1,74 @@
module Shimmy.Spawning where
import Prelude
import Data.Either (Either(..), hush)
import Data.Int (decimal, fromString, toStringAs)
import Data.Maybe (Maybe(..), fromMaybe)
import Effect (Effect)
import Effect.Console (log)
import Foreign.Object as F
import Screeps.Const (pCarry, pMove, pWork)
import Screeps.Game as Game
import Screeps.Memory as Memory
import Screeps.Room (room, setRoomMem)
import Screeps.Spawn (spawnStoreEnergy)
import Screeps.Types (BodyPartType(..), Creep, GameGlobal, Role(..), Spawn)
getLastId :: Memory.MemoryGlobal -> Effect (Maybe String)
getLastId memory = do
res <- Memory.get memory "last_id"
pure (join $ hush res)
decodeId :: Maybe String -> Effect Int
decodeId str = do
case str of
Nothing -> pure 0
Just int -> pure (fromMaybe 0 (fromString int))
encodeId :: Effect Int -> Effect String
encodeId int = do
int <#> (toStringAs decimal)
incrementId :: Int -> Effect Int
incrementId int = pure $ int + 1
namify :: Effect Int -> Effect String
namify int = do
(pure "shimmy") <> encodeId int
getCreepName :: Memory.MemoryGlobal -> Effect String
getCreepName memory = do
currentMin <- getLastId memory
nextMin <- decodeId currentMin >>= incrementId
creepName <- namify $ pure nextMin
(encodeId $ pure nextMin) >>= Memory.set memory "last_id"
pure creepName
spawnCreep :: Spawn -> Array BodyPartType -> String -> Role -> Effect Unit
spawnCreep spawn parts name role = do
res <- Game.rawSpawnCreep spawn parts name role
case res of
Left err -> log $ show err
Right str -> log $ str <> " spawned"
createIdleCreep :: Spawn -> Memory.MemoryGlobal -> Array BodyPartType -> Effect Unit
createIdleCreep spawn memory body = do
name <- getCreepName memory
spawnCreep spawn body name RoleIdle
doSpawnCheck :: Spawn -> Int -> Memory.MemoryGlobal -> Effect Unit
doSpawnCheck spawn numCreeps memory = if availableEnergy > 250 && numCreeps < 3 then do
createIdleCreep spawn memory [pWork, pCarry, pMove, pMove]
else pure unit
where availableEnergy = spawnStoreEnergy spawn
initSpawn :: F.Object Creep -> GameGlobal -> Memory.MemoryGlobal -> Effect Unit
initSpawn hash game mem = do
let spawns = Game.spawns game
spawn1 = F.lookup "Spawn1" spawns
case spawn1 of
Nothing -> pure unit
Just s1 -> do
let r = room s1
setRoomMem r 0 0

11
test/Main.purs Normal file
View file

@ -0,0 +1,11 @@
module Test.Main where
import Prelude
import Effect (Effect)
import Effect.Class.Console (log)
main :: Effect Unit
main = do
log "🍝"
log "You should add some tests."