Page 1 of 1

Feasibility of limiting # of a certain item in game?

Posted: Tue Nov 12, 2019 11:57 pm
by LuxArdens
I enthusiastically started constructing a new overhaul mod, that introduces population and 'labor (force)' as something you have to put on a belt and use to craft objects. Yesterday, however, I realized that there is a critical concept to what I want to achieve, that the entire mod hinges on, and if it is fundamentally impossible, then I better quit right now, rather than waste 1000 hours building a large mod:

The challenge I'm faced with is that I need to limit the amount of items (of a certain type/category only) that are currently in the game to a certain (dynamic) variable. The item must be counter regardless of whether it is in an assembler, on a belt, on the ground, in an inventory or in a chest. Is this feasible? Or is it practically impossible?

I've already found a potential way to actuate the 'limiting' when the count of the item is too high. The issue is in actually counting the number of that item(s) present in-game.

The immediate and impractical approach I thought of would be to have a function routinely check every single tile and object in every chunk, counting up on each instance found. This takes several minutes for medium-sized bases, so it's extremely unusable. I'm not well-versed enough in lua (yet) to come up with something better. Is there a better way? Here are the requirements I determined for the counting function:

- has to count number of specified item OR specified group/category of items in-game
- counted items should include those inside chests, belts, buildings, inventory, ground
- function can be costly. Increasing time per tick by ~25% compared to vanilla would still be acceptable
- count only has to be updated at around once per minute, possibly even less
- The specified item(s) will always be created out of an assembler.
- The specified item(s) will only destroyed when put in a chest and manually shot, or when a biter destroys a building containing it.

Is there a way to program a reasonably fast function for this?

Would it be possible for a function to run every time a specified recipe is finished, and count that way?

Cheers!

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 7:57 am
by PyroFire
It is not feasible, mostly because you can't make the counter event driven, e.g. there is no on_assembler_finished_crafting event.
There is this: https://lua-api.factorio.com/latest/eve ... afted_item but it is not enough.

What is the purpose of this anyway?
There could be a better way to do what you're trying to do without using an item counter and limiter.
E.g. "when max demand for an item is reached, stop requesting said item" for example.
That way when the player reaches the limit, the item is simply no longer requested or consumed until more are needed.

Another idea might be to have a table of items paired with a special entity that only outputs so many at a time - that way you can directly control how many exist in the game at a given time, and obviously count when chests are destroyed.

e.g. my_table={iron-ore=500} if(has_previously_outputted < 10)then my_loader.insert_iron_ore(1) my_table[iron-ore]=my_table[iron-ore]-1 end

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 12:02 pm
by LuxArdens
Ah, thank you, unfortunate that such an event doesn't exist (although I'm sure it's for a good reason).
PyroFire wrote:
Thu Nov 14, 2019 7:57 am
There could be a better way to do what you're trying to do without using an item counter and limiter.
E.g. "when max demand for an item is reached, stop requesting said item" for example.
That way when the player reaches the limit, the item is simply no longer requested or consumed until more are needed.
What do you mean with 'demand' here? Like the logistical system demanding it? Because I need it to work outside of the logistics system.

The measure's purpose is supposed to prevent exploits. Or to provide more context/detail about what it is for:

In the mod, you build a 'house', which for example supports 100 'population'. The Population is just a number and not an actual item in-game, but I want it to produce an item called 'labor' that represents workers, and there shouldn't be more than 100 per house, otherwise there are more workers than there's supposed to be housing for. Labor needs to be recycled after each use, much like the catalysts in Angels for example. The idea of the mod is that the factory will have 'circulation' with lines of fresh workers going in and tired workers going out. If workers can be produced in infinite amounts, then that defeats the purpose. Limiting the total amount of workers also introduces new challenges to the game such as minimizing the travel time to production facilities, and balancing the production numbers.

I contemplated about your idea of having an entity output only a limited amount of the item (e.a. labor), and it is at least a partial solution I think! But the immediately obvious exploit would then be to simply deconstruct/destroy the building after placing it, and with every new building placed, I suppose that the limit would go up?

Or is it possible to decrease the limit every time a certain building is removed? I see there is a "on_entity_died" event, which I assume works for biters and shooting a building. Combined with "on_pre_player_mined_item", would that work to adjust some variable that counts the population?

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 12:28 pm
by PyroFire
Yeah sounds like those houses can just be chests that host a fixed number of "workers", meaning each one will only ever be given 100, or however many.

There are no major exploits by simply counting how many "workers" you initially added to the chests, and by counting when entities are destroyed.
The player will only ever be able to "exploit" up to the number of houses they have at any given point (inclusive of those in inventory).

Nice way to introduce housing/workers/etc too.

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 1:19 pm
by mrvn
Putting people on belts seems kind of odd. So lets change the concept a bit.

What you have are Geothermal plants. Each plant comes with a set number of obsidian bricks. The Geothermal plant is a furnace running on void energy and produced hot bricks from cold bricks. Hot bricks can then be used as "energy source" in other recipes resulting in the item and a cold brick. Thats your basic cycle.

When a Geothermal plant is deconstructed you get an event. In that case you can remember how many plants where deconstructed. Only when as many plants have been put back as where deconstructed you add new obsidian bricks to the new plants.

Problem is that over time you will loose obsidian bricks. For example buildings get destroyed by aliens. Does that destroy the brick? Or does it drop the brick as loot?

Worse: When the user changes a recipe in an assembler the running recipe is lost destroying one obsidian brick. I don't think there is any way to catch that.

On the other hand you can build a Geothermal plant, take out all the bricks and then shoot it till it is destroyed. Now you have created new bricks. Might be expensive but it's possible.


Alternatives:

1) Staying with the Geothermal plant idea. Why not have it create actual heat energy. You can then connect that to furnaces and assembler that use heat as energy source. Every so many assemblers you will need a new Geothermal plant. But there is no physical item that you move around. The plant simply generates N MW of heat that you can use, no more.

2) Why limit the number of items if you can loose them and make more (by building more plants). Why not simply add them as a resource that's rare? You want more obsidian rocks then find more obsidian rocks laying around. Or mine an ore field for them.

3) Lets change the obsidian bricks to energy crystals. Crystals can be grown. You need a seed crystal and some stuff to grow it with and out comes a bigger crystal. Cut that in half and you have 2 crystal. Make it expensive, make it slow. That limits the amount of expansion you can do. It also locks down crystals you could be using in assemblers. Make it take 100 crystals and produce 101 and it will be a major decision to grow more crystals instead of running 100 assemblers.

In cases 2+3 you still have a dependency on the Geothermal plant to recharge the bricks/crystals. So what if the user builds 1M bricks/crystals. Without the Geothermal plants to charge them they are just sitting there useless.

Extra feature: Charging bricks/crystals can be destructive: 1 cold brick -> 99% hot brick. Sometimes the brick breaks from tress. On average a brick can be charged 100 times. Then you need to make a new one.

Update: Building a Geothermal plant can create 100 obsidian bricks too: 20 steel, 2 pumps, 4 heat pipe, 100 cement, 200 stone bricks -> Geothermal plant + 100 heat bricks. No need to create them by magic when you place the plant.

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 1:27 pm
by LuxArdens
PyroFire wrote:
Thu Nov 14, 2019 12:28 pm
Yeah sounds like those houses can just be chests that host a fixed number of "workers", meaning each one will only ever be given 100, or however many.

There are no major exploits by simply counting how many "workers" you initially added to the chests, and by counting when entities are destroyed.
The player will only ever be able to "exploit" up to the number of houses they have at any given point (inclusive of those in inventory).

Nice way to introduce housing/workers/etc too.
Great! Thanks for the help. I think I've got it worked out then. Right now I have this:

Code: Select all

script.on_event(defines.events.on_built_entity, function(event)
if game.entity_prototypes["housing-1"] then
	global.potential_population = global.potential_population+10 -- set variable potential_population +10
	if global.potential_population >9 then 		-- add an if statement to check what potential_population is. If population <10, add none.
		iteminsert{name="labor-1-precursor", count=10}		-- insert an secret item that is the required precursor to make initial labor  (maybe make it so you can't take out the precursor by hand)
	end
	-- set recipe to produce labor
end
And something to tick the counter down when it's removed. So this at least prevents one exploit. The housing also has to execute the recipe to recycle the expended labor though, so it's a little more work to get things working, and I still need to learn lua, but at least it's all possible.

Re: Feasibility of limiting # of a certain item in game?

Posted: Thu Nov 14, 2019 2:12 pm
by LuxArdens
mrvn wrote:
Thu Nov 14, 2019 1:19 pm
Problem is that over time you will loose obsidian bricks. For example buildings get destroyed by aliens. Does that destroy the brick? Or does it drop the brick as loot?

Worse: When the user changes a recipe in an assembler the running recipe is lost destroying one obsidian brick. I don't think there is any way to catch that.

On the other hand you can build a Geothermal plant, take out all the bricks and then shoot it till it is destroyed. Now you have created new bricks. Might be expensive but it's possible.

Alternatives:

1) Staying with the Geothermal plant idea. Why not have it create actual heat energy. You can then connect that to furnaces and assembler that use heat as energy source. Every so many assemblers you will need a new Geothermal plant. But there is no physical item that you move around. The plant simply generates N MW of heat that you can use, no more.

2) Why limit the number of items if you can loose them and make more (by building more plants). Why not simply add them as a resource that's rare? You want more obsidian rocks then find more obsidian rocks laying around. Or mine an ore field for them.

3) Lets change the obsidian bricks to energy crystals. Crystals can be grown. You need a seed crystal and some stuff to grow it with and out comes a bigger crystal. Cut that in half and you have 2 crystal. Make it expensive, make it slow. That limits the amount of expansion you can do. It also locks down crystals you could be using in assemblers. Make it take 100 crystals and produce 101 and it will be a major decision to grow more crystals instead of running 100 assemblers.

In cases 2+3 you still have a dependency on the Geothermal plant to recharge the bricks/crystals. So what if the user builds 1M bricks/crystals. Without the Geothermal plants to charge them they are just sitting there useless.

Extra feature: Charging bricks/crystals can be destructive: 1 cold brick -> 99% hot brick. Sometimes the brick breaks from tress. On average a brick can be charged 100 times. Then you need to make a new one.

Update: Building a Geothermal plant can create 100 obsidian bricks too: 20 steel, 2 pumps, 4 heat pipe, 100 cement, 200 stone bricks -> Geothermal plant + 100 heat bricks. No need to create them by magic when you place the plant.
I just view the people on belts as going to their work on the highway but I like that it discomforted you enough to construct an analogue for it :D

I had to check after you mentioned recipe switching, but luckily the recipe destruction is easily fixed with the aptly named mod "Don't lose in progress ingredients". And there are events for buildings being destroyed as well, so no issues there.

The exploit of putting down a ton of geothermal plants/housing I've already partially fixed by keeping track of the number put down, so you need enough geothermal plants already placed for them to start bricks again.

I already have a mechanic in mind to prevent the minor exploit of simply spamming "geothermal plants", as they'll require constant upkeep. If they no longer receive upkeep, the global production speed of ALL "geothermal plants" goes down, so it's pointless to spam them without being able to support it.

As for the alternatives you suggest:

1. That sounds pretty fun actually! But it only really works for the example with Geothermal you have. For "housing" and "labor" it'd look kind of silly to have them transported along pipes. And I think it'd be a lot harder to design a large factory with heat pipes, than when you're allowed to use belts. Also, heat pipes are already used in-game, so nuclear power would have to be disabled, or you could 'replace' 1,000,000 people with a single reactor :lol:

#2&3 I really want to prevent at all costs. There's a million mods out there that have 'rare' and difficult to get resources or products, but they don't really change the underlying mechanic of how you manage resources. Take refined uranium for example, or fusion in Pyanodon. It's all really hard to get going, but once you have the basics set up, you can just scale everything up and boom, suddenly you have millions of it. There's no added thinking work for constructing 1000 miners instead of 10.

Instead, what I want to do is have these "bricks" be fundamentally limited and require constant upkeep (for the geothermal plants), as well as costs to recycle them. If there's only a restricted amount of bricks, this introduces two magnificent new design and automation challenges:

1. You will be forced to think about distances and travel time, since having endless miles of belt will mean that 99% of your bricks are on the belt, and not doing recipes, bottlenecking production.

2. It also means you have to actually have to think carefully about allocation of resources. For example in normal play, you could be short on say: iron plates. And say you have your circuit assemblers set up on the main bus, before your belt production. That means you only have enough to produce green circuits, but not enough for belts. Well then... who cares? If you just wait a bit, your entire factory will eventually be saturated with circuits (all the assemblers, belts and chests), and after that, iron will go to your belts. There's no real urgency, no need to think about allocation.

In addition: no matter how short you are on iron plates, they'll never, ever kill your ability to produce iron plates themselves. There's no negative feedback or real system, it's just a big forward line of recipes. The only situation where that you do have (catastrophic) feedback is in power production. Failing to produce enough power often leads to you having even less power, and eventually you get a blackout and you have NO power. That's why you have to think about power production, and you have to prioritize it and construct circuit networks for it and dedicated miners. I want a similar thing for the "bricks".

Re: Feasibility of limiting # of a certain item in game?

Posted: Fri Nov 15, 2019 2:56 pm
by PyroFire
I made a working prototype of this mod that procedurally parses the technology tree to generate energy tokens based on science packs.

credit to LuxArdens for the idea.

https://mods.factorio.com/mod/scientorio

Though i suspect you have other ideas about how such tokens should be managed.
Procedural generation can only do so much.

Re: Feasibility of limiting # of a certain item in game?

Posted: Sat Nov 16, 2019 3:52 pm
by LuxArdens
PyroFire wrote:
Fri Nov 15, 2019 2:56 pm
I made a working prototype of this mod that procedurally parses the technology tree to generate energy tokens based on science packs.

credit to LuxArdens for the idea.

https://mods.factorio.com/mod/scientorio

Though i suspect you have other ideas about how such tokens should be managed.
Procedural generation can only do so much.
That's an interesting take on it! I wanted to try your mod, but it gives a ton of errors on load...

Re: Feasibility of limiting # of a certain item in game?

Posted: Sat Nov 16, 2019 8:40 pm
by PyroFire
LuxArdens wrote:
Sat Nov 16, 2019 3:52 pm
That's an interesting take on it! I wanted to try your mod, but it gives a ton of errors on load...
It's likely one of the mods you have installed, as i haven't completely tested it with mods.

Re: Feasibility of limiting # of a certain item in game?

Posted: Mon Nov 18, 2019 2:14 pm
by Honktown
I didn't read all of the thread, but a possible solution: Watch the production statistics, and when the limit is hit, disable the recipe and clear anything that can produce it. Re-enable the recipe if more houses were built If a specific building is used (like a rocket silo has a fixed-recipe) then you only need to check one class of entities, which can be kept in a list. If the people can be... removed then things get complicated.