Maps

by Pi-C

You may find a map of the region by destroying trees and enemies. Collect maps around the world to quickly discover the area around you! But beware: if you kill a tree, you may wake up hidden enemies instead of finding a map.

Content
1 year, 6 months ago
0.16 - 1.1
841

i Does this mod simply charts chunks?

3 years ago

I'm curious that if it is possible to lock areas until people find the maps.

Simply create another surface as the source of copying. When map is found, copy some chunks to the default surface, which enlarge the playable area. In this way, people simply don't feel the parallel surface exists, and the new "generated"(actually pasted) chunks are very natural since they are generated by the vanilla algorithm.
And if you have done the upper part, it's possible to add maps that generate ores and crude oil on the ground.

3 years ago

I'm curious that if it is possible to lock areas until people find the maps.

Interesting idea, but …

Simply create another surface as the source of copying. When map is found, copy some chunks to the default surface, which enlarge the playable area.

… maps are not guaranteed to exist everywhere. Big maps are spawned with a 0.005 probability, the smallest maps with a probability of 0.015 when killed by a player (killing means by use of weapons, not by mining a tree) -- unless the target (tree, spawner, or worm) is killed by fire or an explosion (small and medium maps are removed in that case, and big maps are replaced with scorched maps). If mods like Wild fire are used, trees may also catch fire from natural causes, in which case all maps are removed.

If you start in a desert area, wood is precious, you need to mine it at the latest when you need wooden poles, so you don't want to waste ammo by shooting trees without yielding wood. So, in the worst case, you'd be stuck in the starting area because there are no maps.

Also, what about radars? They uncover new chunks. It may be possible to cripple them so they display only the current chunk (but what if they are placed at the border?), but I don't know. Abolishing radars altogether would be bad because they are needed in bigger bases so that you can check what's going on in a distant outpost without moving there.

How about a player moving to the edge of the charted area? I could imagine that there's a trigger area some tiles before you reach the border where the new chunk will then be generated -- how to cope with that?

3 years ago
(updated 3 years ago)

Alternative suggestions:
1) When a map is to be generated, check if the area it shows covers uncharted areas. If all of the area is already known, remove the map. It still may happen that a big map is generated next to a small map so that the small map would become useless. But checking if an area is already completely revealed is expensive:

We first need to check that all of the 4 corner points of the square ABCD around the map are in charted chunks. If that's the case, we need to assert next that the lines AB, BC, CD, and DA don't go through uncharted chunks. A chunk is 32 tiles wide, the small map has a radius of 100 tiles (i.e.the distance between A and B is 200), and the big map has a radius of 300 (so AB = 600). So after we've made sure that A, B, C, and D are all in charted chunks, we need to go along the lines AB etc. and check at every 32 tiles if that point also is in charted area. We can stop if we find one point that's in uncharted area.

Worst case is that the area has been completely charted. In that case. we need to check

4 + 4*int(2*radius/32)

positions (i.e. 28 tests for each small map and 76 tests for each big map) before we can be sure that nothing needs to be done. I don't know how expensive position checks are -- perhaps they have no impact at all, perhaps it is immense.
2) Don't chart around the map's position, but chart a random chunk. This could be bad for performance as far-away, unneeded chunks are generated.

3 years ago

1, if you chart any place with code, the game seems to be forced to generate the relative chunks for you. If you call that function in your backend surface, I think the game generates the copying source.
2, If radars are put in the edge, where could be terrain tiles, but due to my suggestion, they should be void. What you have to do in code, is surface::set_tiles in on_chunk_charted. Notice ,not in chunk generated, but in charted. Set the extra tiles to "out-of-map". Any trouble with the prototypes, you need the mod named lua api global variable viewer. You'll see a lot chats there between the author and me.
When the condition is fulfilled, the terrain should be back to it's place, set_tiles again. But logically, this time is copying.

3 years ago

btw, the checking of whether a chunk exists, actually not very expensive.
Do you need any test? I could make one for you. Within that, I'll implement all my suggestions. If everything goes well, it shouldn't be long. A day or 2.
All I need is being credited. With any title you prefer.

3 years ago

I'll think about making uncharted areas inaccessible. It is dangerous because if things go wrong, players could get caught in a small area with no way to expand their factory. Players on an enemy force would just have to make sure they kill all trees collect all maps. (OK, spawners and worms also give loot, but they are much harder to kill than trees and there's no guarantee that a couple of spawners in your starting area will leave any loot.)

For now, I'm already testing my first suggestion (yes, scanning the chunks in a map-sized area is reasonably except my Factorio computer has been hanging for almost an hour, because I've given it too many chunks to test for, some heavy swapping going on, so I guess it's still calculating. :-))
I think not having too many maps is good enough for the beginning. If they are more rare, they increase in value, so there even is an incentive to hunt for maps left on account of an enemy player force -- without ruining their game by locking them in.

So let's test that first! (Meanwhile, my computer has come alive again after a good 65 minutes and is trying to keep up with all the key presses and mouse movements it has missed while being asleep. I can now officially confirm that checking all 4 million x 4 million tiles is not a good idea :-D)

3 years ago

1, pvp is bad idea.
2, It's possible to create trees, spawners in code. And if people run out of maps, you could find the eneity and check if they are truly stuck in their place and create new chunks for them in code.
3, If your computer hangs on for a whole hour, 99.9% it goes into some infinity loop.

3 years ago

1) Good idea or bad idea -- people will try (see 3).

2) Yes, it's possible. But that would take some serious work and turn this mod into another monster. The mods Dell Aquila made were all very simple: just a new prototype definition, rarely a bit of control scripting. As soon as I touched the other mods I've inherited (especially Water Turrets and minime), they have turned into complicated beasts that were interesting and fun to make and add some value IMHO, but all of a sudden I had to take care of things like multiplayer desyncs, storing player data across sessions and making them accessible from data and control stage. These things are prone to introduce errors that require more fixing and take more time than I really wanted them to. I want to avoid that with Maps -- especially as I need some time to work on the other mods that I still need to update for Factorio 1.0. I may change my opinion about blocking access to unexplored areas later, but for now let's keep it as it is. (It's not that your idea is bad -- I'm just afraid things will quickly grow over my head again.)

3) It's definitely not an infinity loop -- just some huge but finite numbers for a benchmark. This one-liner is what did it:

/measured-command do local size = 300; local tl = {x=-size/32, y=-size/32}; local br = {x=size/32, y=size/32}; local test; for x=tl.x, br.x do for y=tl.y, br.y do test = game.player.force.is_chunk_charted("nauvis", {x, y});  end; end; end

That' returns the time spent on checking the area of Big maps, and it's not much. But use "size = 2000000" (I believe that's the maximum number of tiles in each direction from the starting area that Factorio allows), and the time will increase dramatically. Yes, I knew before I started that it may be risky, but I wanted to give it a try nevertheless (see 1).

3 years ago

I'm not sure, but according to my coding experience, all the chunks are given by game in 32 by 32. No exceptions found till now. So, you could simply track all the charted chunks in a table. In my way, it's:
charted_chunks = {}
charted_chunks.has_chunk = function(x,y)
if not charted_chunks [x] then return false end
if not charted_chunks [x][y] then return false end
return true
end
And then, for the on_chunk_charted, I simply do this:
if not charted_chunks [event.position.x] then charted_chunks [event.position.x] = {} end
if not charted_chunks [event.position.x][event.position.y] then charted_chunks [event.position.x][event.position.y] = {} end
Now I have a table for quick look-up. And the table is capable to handle all the information associated with chunks and even tiles.
This is very fast in my code.

3 years ago

Chunks are charted per force, so to be prepared for multiplayer, you must keep a chunk list for each force that has players. Sure, you'd probably get away with storing just a boolean value per chunk, but with huge bases, the sheer number of chunks will get impressive, so it may impact save file size.

Mods may allow players to change their force, declare independence or merge forces. It's easy to add data for a new force -- but how about a force that was created and had players, but they all left their old force and joined different team, so the old force has no players left. Keep the list of charted chunks for that force because players may have joined another force just temporarily and may come back? Could result in needless data carried on in the saved games. Delete the list? If somebody joins the force again, we'd have to rebuild the list…

Also, what about chunks that are uncharted by a mod (not deleted, just uncharted)? There's no event we could react to, we can't remove those chunks from the list, so we must assume that it won't reflect the real state of the chunks at all. (So, after looking up a chunk in the list, we'd still have to check if it's charted, which defeats the purpose of the list.)

Look-up lists are simple (I've already suggested something very similar here) and quick, but still require some overhead.

3 years ago

I'm not sure, but according to my coding experience, all the chunks are given by game in 32 by 32.

Just consider:
Tiles: 300x300
Chunks: 88

Tiles: 1000x1000
Chunks: 977 (Rounded up to next integer here and in the following)

Tiles: 10,000x10,000
Chunks: 97,657

So your list will grow very quickly.

No exceptions found till now. So, you could simply track all the charted chunks in a table. In my way, it's:
charted_chunks = {}
charted_chunks.has_chunk = function(x,y)
if not charted_chunks [x] then return false end
if not charted_chunks [x][y] then return false end
return true
end

You can optimize the test a bit:

if not (charted_chunks [x] and charted_chunks [x][y]) then return false end

Should work just the same because the part after "and" won't be reached unless the part before it is true.

New response