Just so you know, you are asking for what is close to a framework, not a snippet. Path re-use is one of the more complicated tasks to undertake in Screeps.
Posts made by MyrddinE
-
RE: Example for storing and using a path in memory?
-
RE: New Programmer
The documentation is very good covering 'What does this command do' but mediocre to poor on 'What are the ramifications of this' and 'How do I accomplish common tasks'.
A good example is creep parts. There is precisely no coverage of 'how many move parts do I need for different situations' or 'how much claim is enough' or 'what does my creep cost per tick' or 'when is it worth it to boost a creep part'. Answers to all these questions require a lot of math, spreadsheets, or experience and none of it is explained in any documentation despite being critical information for decision making.
It can all be derived from the given information, but that's not the same as being explained. There are many systems in the game that have no explanation of how they work, and no intuitive understanding can be made without doing math. This is in contrast to other RTS games that draw on real life to provide context and intuitive understanding of the relationship between units. Because we are require to build every unit ourselves from scratch, but are given no context about what makes a good unit for different roles, it's a serious sticking point for new players.
Programming is difficult... programming when you don't even understand the system requirements is much harder. The documentation does not provide a surrogate 'expert user' to get domain knowledge from. It should.
-
RE: Confusing information - Memory CPU use in parsing
A single large variable will be faster to store and restore every tick than an equivalent amount of data stored in many small variables.
The decision of whether you should store one big variable (and parse it out yourself) or many smaller variables (and let the built in code handle everything for you) depends mainly on two factors: "Is it worth optimizing yet?", and "Do I access all this data every time, or frequently access only part of it?"
For example, the system stores the room cost matrix into a single variable, because when you are making a path you usually need most of the matrix anyway. But paths are stored as an array of steps, because you usually only need to see one step (the next step in the path), and there is no reason to decode the entire path out just to retrieve one step.
It's important to understand that the built-in memory handling uses memoization: you don't pay the decoding cost until you access the variable. So if you don't read the value of a piece of memory it never gets decoded.
Because of all these factors, the real answer is 'it's complicated'. But in general, if you are storing an array of arrays directly into the memory object, you're probably doing it inefficiently. If access to that memory is frequent, then it's likely eating up a notable amount of CPU and it's worth looking into squishing it into a big string and parsing that string into the full array yourself.
-
RE: Hiding specific Flags
That's not a bad suggestion, but you could easily fake it you know with some code of your own.
You could use a custom flag finder that EITHER returns a visible flag OR returns a position object tied to a deleted flag's memory. Flag.hide could delete the flag but not the memory, and store the position and color into that memory location. Flag.show would create a flag with the old name, pointing at the old memory.
Some tedium to set up, but should be CPU efficient and emulate the exact result you want.
-
RE: This should go in the next Screeps World Review
I find it funny (and sad) that the author of the message doesn't seem to have a recovery code path for when the hauler dies without enough energy to replace it available to the Spawn. His room has been ticking down for ~12 hours.
-
RE: Quick room finder
I agree a search tool would be nice (or just making common criteria, like 2 available sources and no enemy connected, highlighted on the map). But two sources is just fine in a room; I don't think more are necessary at all.
-
RE: Unwritten rules of conduct?
I agree that respawning into a newbie area and harassing inexperienced players is detrimental to the longevity of the game. I believe that newbie protection is too short.
On the other hand, it is that short, and re-spawning to a new location has very few costs associated. If the player did not have a tower up then in less than a day they could recover their previous glory in a new location with their improved code. What I do think should be clarified and emphasized to players is the importance of their code being able to bootstrap itself from nothing-to-defenses on its own in a new room. If players have that as their goal then having to restart is simply another chance to see how well their code bootstraps a new room. That goal is under-emphasized I think, and that can lead to players thinking that starting over really means starting over, rather than 'another chance to test my code'. It's a perception thing, and I don't think the current tutorial and documents encourage the right perception.
-
RE: StructureSpawn.spawning not updated same tick
StructureSpawn.createCreep does not create a creep that very tick. Like all commands, it actually begins on the next tick. Unfortunately only Creeps allow you to cancel a pending order (it would be nice if that could change), and if you want to remember what orders you have made this tick you need to keep track of it yourself.
What does happen immediately when you use the createCreep command is the adding of the optional memory object into Memory. But the actual creep creation has not begun, and so StructureSpawn.spawning is correctly false. It's not hard for you to manage your own flag on whether you have ordered a creep this tick or not.
-
RE: Creeps all dissapear
Can you describe the room and tick when it happened? The History being blank is a bug, but it's possible you got invaded. They only last 1500 ticks (just like your own creeps) so they often sweep through, kill your creeps, then expire before doing much structural damage.
-
RE: Questions on roles
Multi-role creeps are rarely efficient. For example, anytime a balanced (MOVE/WORK/CARRY) creep is harvesting a source into a container, all those MOVE and CARRY are wasted. Even builders and controller-upgraders should have different bodies, because a builder moves a lot and burns through 5 energy per tick (per WORK), while a controller moves rarely and burns through only 1 energy per tick (per WORK). So a builder needs more MOVE and CARRY than an upgrader.
-
RE: [Resolved] Massive script error
At some point your script got an object (perhaps using GetObjectById), or it searched for an object using a Find method, but there was no result (a Null instead of an object). Your script didn't check, it just assumed the method returned an object. You need to check.
-
RE: Questions on roles
You need to understand how movement works before you can make informed decisions about creep bodies and roles.
- A creep that is 1/2 move parts can always move full speed over plains.
- A creep that is 1/3 move parts can always move full speed over roads.
- Empty carry parts don't count for movement, so empty haulers move at full speed even over swamp.
- Move parts are a waste if you don't move, but taking too long to arrive is a waste of the creep's life too. Some math can demonstrate:
[WORK,WORK,WORK,WORK,WORK,WORK,MOVE] = 650 energy. Without roads, it will take 150 turns to move 25 squares. That's 10% of its life, or 65 energy, wasted. This makes its 'real cost' 715 (because you would need to spawn its replacement 150 turns early to not have a gap). But adding another move part is not efficient, because this would raise the cost of the creep to 700 energy and lower the 'time cost' of travel from 65 down to 35. Total cost now? 735 energy.
The move expensive the creep gets, and the longer it has to spend traveling, the move move parts you should add. Your situation (distance traveled over the life of the creep, roads, swamps) will define the optimal choice for you.
One thing I recommend: keep track of your time spent moving, working, and idling on your creeps. When they die of old age, report this information in to some kind of statistical memory. That will help you make informed decisions about whether your creep body designs are fulfilling their role efficiently in your circumstances.
-
RE: container.room incorrect
That does appear to be a bug.
On a different note, this exact bug is why I have my IDE flag the use of assignment in conditionals as 'probably wrong', and why I trained myself to put constant first in tests ("E34S11" == creep.room.name) so that missing an = sign causes an instant error.
-
RE: structure.say
Go one step further, and use MapObject.say(). If it has a position, it can talk. I also don't see any obvious reason why you can't have enemy creeps talk (to you). Since .say() costs 0.2cpu to call it's not like it can be abused. Better (server performance wise) to use say() than to spawn flags for debugging.
-
RE: Storing a variable callable from several different creeps.
All RAM is reset, every tick. All code outside of exports is only called randomly when the code cache regenerates (which happens after you commit new code, but also randomly at other times).
The only persistent state is what you store in the Memory object, which is automatically serialized between ticks. You get 2MB of serialized storage; that is all the state you can store.
You cannot serialize game objects or functions. Because of this the best practice when you want to store a game object (like you are describing) is to store the id. For example:
-----------------
let currentConstructionSite = dispatcherConstructionSites.GetConstructionSite();
creep.memory.myCS = currentConstructionSite.id// later
let myConstructionSite = Game.GetObjectById(creep.memory.myCS)
-----------------
The takeaway is that code persists, RAM does not, unless you serialize it into the Memory object (linked by ayrtep above).
-
RE: Storing a variable callable from several different creeps.
@ayrtep, I got the impression from his question that he meant a variable holding a function, since he asked for one that was 'Callable'. You can't store a function pointer into Memory, as functions are not serialized.
-
RE: Storing a variable callable from several different creeps.
This is not an easy question to answer because it highly depends on your code architecture, and I have no idea how your code is structured.
Global variables are bad, 'mmkay. But you can always have a module that all the other modules load, and call it Global or something.
Global = require("global");
Global.variable = 3; // visible everywhere "global" is required, assuming you exported a property of that name.
-
RE: need help learning the game
"I don't care whether the tutorial is considered a good one or not, I'm only interested in learning, and not interested in critiques either of myself or the instructions."
That is the tone, because that's your initial post. You didn't ask for assistance learning, you criticized the documentation. That naturally led to those of us who did fine with the documentation confused as to whether you had seen the same documentation we had or whether you were new to programming in general.
If you are looking for alternate modes of assistance to the documentation and tutorial I highly recommend the Slack channel for Screeps, linked at the top of the discussion board pages. It's active at all times of day, and you can certainly find help there. There are also several different GitHub projects with the code of various players available for perusal; if you learn better by reading others' code that may work well for you.
-
RE: Error Code List
The ERR_ constants near the top of this tall page are your answer.
http://support.screeps.com/hc/en-us/articles/203084991-API-Reference
Also, this would have been hinted at (but not explicitly stated) in the very first tutorial steps. The line that says: "if(creep.harvest(sources[0]) == ERR_NOT_IN_RANGE)". It's checking the return value against a constant. You just need to find the definition of the constants.
-
RE: Collaborative Endgame
I think two worlds... a persistent one, and a seasonal one, would be a nice enhancement to the game. The seasonal game could be subscriber only, and thus provide an incentive to purchase a subscription to 'test out' your code for a limited time. Since a season will be of a limited length users could purchase a set amount of months and compete on a level playing field with everyone else.
This helps reduce the perceived cost of subscribing to an MMO because it's for a prescribed period of time and thus for a fixed amount of money. This differs from the persistent world where you have the fear of paying for X amount of time... but then when your subscription lapses and you fall back down to 10CPU your progress is halted and your creeps languish in eternal CPU drain until your empire crumbles. Not an enjoyable prospect to look forward to.
TL;DR: I think seasonal subscriber-only shards would be a good way to lure new players into subscribing due to the level playing field and fixed duration.