Game.cpu.generatePixel change


  • Dev Team

    @systemparadox If you have negative bucket at the start of the tick, it will be skipped with an error Script execution has been terminated: CPU bucket is empty.



  • Ok I don't think @cribbit realised that.

    What if you charged 10K but the extra CPU did carry over like normal. Does it work like this:

    • Tick 1 starts with 9950 bucket and has 100 CPU allocated
    • Tick 1 executes generatePixel, costing 10K CPU
    • Tick 1 does some other stuff costing 40 CPU
    • Tick 2 starts with 10 bucket

    I think this does introduce some interesting challenges and decision making:

    • If you don't have enough bucket to start with, you lose a tick
    • If you spend too much CPU in tick 1, you lose a tick
    • If you spend too much CPU in tick 2, you lose a tick

    The challenge is getting enough bucket in the first place (9000 bucket is easy, but getting a full bucket seems quite hard because of periodic tasks), and in how close you can skirt the CPU limit vs the risk of losing a tick if you run over by mistake.

    This seems much more interesting and doesn't feel like the only way to participate in pixel generation is to opt out of the game entirely for a tick.


  • Dev Team

    @systemparadox This was our initial idea, but we thought displaying a console error and losing a tick is more harsh than cancelling intents only and keeping all calculations. But if enough people tell it's better, we may use this idea instead.



  • @artch said in Game.cpu.generatePixel change:

    @cribbit But then you will lose the entire tick, and not just intents?

    Do we not get CPU allocated per tick?

    I thought it was:

    You have 20 + GCL * 10 CPU for the tick

    If you go over, you can use up to 500 from the bucket, if available

    If you go under, any excess is given to the bucket, which is capped at 10k

    So what I'm saying is:

    generatePixel costs 10k from bucket, plus however much CPU you do not use that tick (eg 150 CPU given for that tick, you use 50, the last 100 does not go to bucket)

    So the tick you generate pixel and the tick after you cannot use bucket, and the ticks beyond that you have to be careful to gain some buffer back before you do anything big.

    That, to me, would be a much more interesting challenge, and one that goes to the core of the performance question of the game. (it also doubles pixel generation cost, which I think would help with their pricing)

    I think the only concern with that setup is it does not play nice with VM resets, so we would either need some indicator that a reset is coming (which I'm assuming can't be done?), or be given an arbitrary higher CPU cap on a VM reset tick.



  • Taking 9900 CPU is better than the current purposed solution. Still going to see a lot of players probably skip this feature, but it isn't as bad.

    ๐Ÿ‘‚๐Ÿ‘๐Ÿ‘†


  • @artch said in Game.cpu.generatePixel change:

    @systemparadox This was our initial idea, but we thought displaying a console error and losing a tick is more harsh than cancelling intents only and keeping all calculations. But if enough people tell it's better, we may use this idea instead.

    I think the whole point is that we have the opportunity to avoid this if we can handle it well in our code. I'll take the risk of losing an entire tick over a guaranteed loss of intents any day.

    As far as I'm concerned a tick without intents is a lost tick anyway. I suspect the majority of players would feel the same way.



  • @artch that's all you have to say to an idea that's trying to catch your points and addressing the overwhelming concerns in the community?

    I am not sure if you even have slightest respect for your community at all.

    The proposal of CONSECUTIVE calls means you have to commit long term to a specific amount instead of paying whenever the bucket is full. You need to actually know how much CPU you can spare. And by not working on the bucket, but CPU it โ€œhurtsโ€œ more.

    I would have wanted you to respond in more detail than just โ€œthis sounds boring to meโ€œ.

    ๐Ÿ‘๐Ÿ‘‚๐Ÿ‘†


  • @nobodysnightmare it was probably unfair to accuse you of not respecting the community... I can't undo that I said that.

    It is just not visible to me how you care about the negative responses you get here and how you weigh the constructive feedback that you receive.



  • @nobodysnightmare This is actually more receptive than usual unfortunately...



  • @nobodysnightmare Let's not turn this into a contest of egos thing; we're just trying to find a solution to a problem โค And it seems like we've found one by simply increasing the bucket cost of generatePixel to 10 000 -> The simplest solutions are often the best for situations like these.

    @artch For as much detail as I put in the post, I apparently didn't put enough if you thought that ๐Ÿ˜ฎ It's okay though; thank you for seeing the community's concerns seriously and for the patience you've shown in the face of such hostility ๐Ÿ™‚

    โค

  • Dev Team

    @nobodysnightmare Consecutiveness of calls doesn't change anything. You simply wait until your bucket is full (one if) and spam chargePixel until the pixel is generated. No risk, no challenge, too easy. Extra rules can make it more difficult, but a good mechanic is a simple mechanic.

    Negative feedback is clearly visible but expected. It's just unclear whether it is an indicator of the mechanic being bad or simply unpopular. Unpopular change does not neccesarily mean a bad change.

    โค๐Ÿ‘Ž


  • @artch The challenge comes from the implications, not the directly-written-code. "Simply wait until your bucket is full" is already the state of affairs for all proposed solutions so far; what makes my idea different is how consecutive calls costing active CPU instead of bucket CPU is in how it limits the player's longterm CPU consumption.

    Consider the following:

    1. A player can use, at most, 500 active CPU per tick.
    2. A player (assuming GCL 30) can produce, at most, 300 active CPU per tick.
    3. chargePixel exclusively consumes CPU from the active production.

    In the following example: chargePixel could be set to consume 400 CPU for 30 ticks.

    1. This limits the player to 100 active CPU per tick <- this is down from 300, and certainly down from the highest-at 500.
    2. This draws 100 CPU from the bucket per tick.
    3. This removes 6000 CPU from the system overall.
    4. MOST IMPORTANTLY: If the player uses more than 100 CPU in a tick while using chargePixel, it'll result in premature script cut-off due to going over the limit.

    In order to make the above work, there'd have to be a rule "generatePixel can only be used if it's the very first intent, otherwise it's ignored" to prevent going around the fourth point. Hopefully, this clarifies where the challenge comes from -> It's about committing to having sustainably higher efficiency code. That is the challenge โค


  • Dev Team

    @neyazayah said in Game.cpu.generatePixel change:

    MOST IMPORTANTLY: If the player uses more than 100 CPU in a tick while using chargePixel, it'll result in premature script cut-off due to going over the limit.

    This can't be done. It's not how CPU limits in Screeps work, an in-game call cannot reduce CPU execution limit within the current tick.



  • Like the others, I think this is a strange and abrupt way of dealing with the overly simplistic generation of pixels. Perhaps instead you could make it behave more like Bitcoin mining and self-balance:

    EDIT: hadn't read post immediately above, crossed out impractical bits.

    • Introduce a "hash function" as Game.cpu.hash, which is artificially expensive and actually taken off the current tick's use (e.g. 100CPU). You could implement this behind the scenes as an HMAC with a per-shard secret, so people can't actually implement it.
    • Introduce a "difficulty" level for the "Pixel Chain". You have to find an input in a particular format (e.g. ${shard}-${Game.time}-${random} that has a hash value below that difficulty (interpreted as a number in ?-endian order).
    • Submitting an entry could also cost CPU to "validate" (whether or not it's correct) and have to be done in a particular tick used as part of the input. This means you need to have enough left over after generating them to submit it...
    • Perhaps a penalty if you sub invalid inputs?
    • Periodically update the difficulty level to reflect the amount of mining happening, targeting a constant generation rate. People then have to decide what their CPU is worth...
    • When people get this right, you could give them a batch of pixels at once, introducing more randomness to the process. Nothing, nothing, nothing, 100 pixels!, nothing, nothing...


  • @artch Strongly against original idea for reasons already stated. Interested in multiple calls version as it's more interesting than "low bucket code".

    My proposal for multiple calls version: It takes HALF of your normally available cpu/tick for the FOLLOWING tick and requires calls for as long as it takes to build up 5000, shard specific. New pixel API with a pixel progress response for given shard (eg, charging pixel at 400/5000). This is useful for other things besides just pixels as it's good practice for reserving cpu for military operations or autoscaling for shard cpu allocations. To increase difficulty you could limit bucket usage as well.



  • @artch I think I understand what you mean, but there are several ways around that problem.

    1. We could have the function cost a constant amount, similar to how intents already cost .2 CPU (and only allow its usage if there's the required amount's CPU available).
    2. Or we could have the function affect the next tick by artificially (and temporarily) lowering the player's GCL (possibly to negative values).

    Both of these things are malleable, as far as my understanding at least.

    Also, what @Davaned said is another way ๐Ÿ™‚



  • @neyazayah Definitely definitely not by lowering gcl. That's a huge pile of side effects that are 100% not feasible and not correlated directly with cpu anyway as it's decoupled once you reach GCL 28.

    Shards already have cpu allocations, we should just use that as the means for handling pixel generation. Decreasing the allocation temporarily (equivalent to allocating a chunk of cpu to another shard/the pixel factory) would lower the barrier to entry for cross-shard play by making related code multipurpose.



  • @davaned Oh, yes! I'm not familiar with the intimate details of the game's programming, so I missed that part.

    There could be an "artificial shard" that the player dedicates CPU towards, and that is what generates the pixel? However, what @artch wants is challenge, so maybe there's a cooldown? How else might we make that challenging?

    Edit: Or are you simply saying that this is just the mechanism by which CPU is removed, and everything else about the idea remains standing?


  • Dev Team

    I still think we need a simple elegant solution here, not a whole lot of new API and inter-tick state data. Currently only two alternatives are on the table: cancelling intents or 10000 CPU cost. Let's discuss them.

    ๐Ÿ‘


  • It seems to me that a next-tick effect is analogous to upgrading a controller or trigger a creep spawn. This tick I perform an action, next tick I see effect and resources are gone. The one informational api would just be a counter.

    But if you feel it's unworkable, in that case 10K is preferable to the shadow canceling of all intents. Although if the goal is balancing number of pixels I'd argue for slightly under 10k (9.5k?) to reduce edge cases. I still think the original way will likely result in players ignoring it or handling pixel gen in another shard.

    ๐Ÿ‘