Stellaris

Stellaris

Origin: Jovian League
doctornull 5 Jan, 2022 @ 3:30pm
Map Generation Heuristic
Here's a simple heuristic which should make pretty and better-connected maps:

1 - setflag on the neighbor systems so you can find them later ("JOVIAN_LEAGUE_EX_NEIGHBOR" or whatever).

2 - Remove hyperlanes and create a wormhole as you do now.

2b - Put another flag on the wormhole system itself ("JOVIAN_LEAGUE_WORMHOLE_EXIT") and find all systems up to some distance (maybe 3) from the wormhole exit system. Put a flag on all of them ("JOVIAN_LEAGUE_DONT_LINK") which have the EX_NEIGHBOR flag.

3 - Choose a random system which has flag JOVIAN_LEAGUE_EX_NEIGHBOR and does not have JOVIAN_LEAGUE_DONT_LINK and does not have JOVIAN_LEAGUE_WORMHOLE_EXIT.

3a - setflag DONT_LINK on the random system and all other systems within some distance (maybe 3) of the random system which have the EX_NEIGHBOR flag.

3b - Create hyperlink from the random system to the wormhole exit.


Repeat step 3/a/b around 6 times and you'll handle vanilla maps.

After that, there should be no EX_NEIGHBOR systems which need links, so you can safely link all remaining (EX_NEIGHBOR and not DONT_LINK) to the wormhole exit. That will handle non-vanilla maps.
< >
Showing 1-12 of 12 comments
corsairmarks  [developer] 5 Jan, 2022 @ 8:44pm 
That's similar to what I'm looking into.

Here's code for "flag all the neighbors"
event_target:jovian_league_system = { every_neighbor_system = { remove_hyperlane = { from = this to = prev } set_star_flag = jovian_league_starting_neighbor_system@prev.owner # TODO: add a nexus wormhole, or something else? } }
Marking the exit is easy enough since I already have a reference to it. I'm looking into using the "distance" trigger to find all systems within X jjumps of the exit. I think I can do it with an every_system loop, limited by the "distance" trigger.

As for repeating 6 times - is that a sort of guesstimate that it's got a high enough chance to get things linked up? I'm not super familiar with the hyperlane generation strategy. I can say that the normal isolated Avatar system doesn't have this issue, since it' spawned by an event post-game-start.
Last edited by corsairmarks; 5 Jan, 2022 @ 8:50pm
corsairmarks  [developer] 5 Jan, 2022 @ 9:02pm 
I was originally thinking of doing a couple passes. Efficiency is secondary since it happens only during galaxy generation.

1. Before removing hyperlanes, flag all the hyperlane neighbors
2. For every hyperlane neighbor, determine how many jumps are needed to get to each of the other neightbor systems - flag them with dynamic flags indicating the game thinks system A is between 2 and X jumps (10?) of system B.
3. Remove the hyperlanes
4. Go through each of the ex-neighbors and verify that each pair of systems that were within X jumps are connected within at least 2X jumps (or some other scaling factor)
5. Any system that can't reach all previously "linked" systems is then linked to the nearest (Euclidean) ex-neighbor to which it does not already have connection, and then checked again - until every ex neighbor can get to every other ex-neighbor (to which it previously had a path) within 2X jumps.

I suspect in most cases one 1-2 hyperlanes will need to be created to get everything fully connected. I am slightly worried that it could lead to a sort of "ring" that still doesn't connect to the galaxy at large.
Last edited by corsairmarks; 5 Jan, 2022 @ 9:04pm
doctornull 5 Jan, 2022 @ 9:26pm 
If you do step 2 before removing the hyperlanes, all neighbors will be distance 1 or 2 -- since every neighbor links to the home system, they are guaranteed to be able to reach each other through the home system, which is 2 jumps max.

So I don't think step 2 is worth measuring.

Also, IMHO you don't need to care about preserving relative distances. As long as the map can be traversed, to me it's playable.


Regarding the 'ring', it's not a concern. If the graph was connected (i.e. you could plot a path from any node to any other node) before removing the home system, then attaching each neighbor to any other node would result in an equally connected graph.
corsairmarks  [developer] 5 Jan, 2022 @ 11:17pm 
I think part of the trick will be picking what "non-ex-neighbor" to connect to. The nearest non-ex-neighbor which has at least 1 hyperlane that also leads to a non-ex-neighbor is probably a good candidate to connect. I could also add a "2nd tier" flag so that adding new connections doesn't accidentally all target the same non-ex-neighbor system.
doctornull 5 Jan, 2022 @ 11:20pm 
Don't connect non-ex-neighbors though?

It would be 100% correct and preserve all connected paths to just link every ex-neighbor to the wormhole exit.

What I'm doing with the heuristic is trying to link fewer ex-neighbors to avoid pathological cases like being in the middle of a cluster, but ONLY ex-neighbors are ever candidates.

Only link (some) ex-neighbors and only link them to the wormhole exit system.
corsairmarks  [developer] 5 Jan, 2022 @ 11:39pm 
That could still form a weird isolated section like this. https://www.screencast.com/t/XvX3Ko5qMd70 I think it's important to make sure a (relatively short) path also exists from each ex-neighbor back to the exit system.

Green are the wormhole-connected systems, orange are the other ex-neighbors.

[edit] I'm concerned with "how can I write code to detect these scenarios" and I think the most reliable is to ensure every ex-neighbor has a path (whether direct or not) to the exit system.
Last edited by corsairmarks; 5 Jan, 2022 @ 11:43pm
doctornull 5 Jan, 2022 @ 11:46pm 
Yeah, what the heuristic does is remove candidates where a short path to a connected ex-neighbor already exists.

I think that both orange systems should connect to the wormhole exit, and it's fine that they are technically already connected by a relatively long path.
corsairmarks  [developer] 6 Jan, 2022 @ 1:28am 
May have to settle for no heuristic. I'll try a few more things tomorrow, but the "distance" trigger is having difficulty checking distance at game start. As a guess the game hasn't computed them yet.
doctornull 6 Jan, 2022 @ 6:43am 
Ah, too bad.

Well, it sounds like your fix will solve the actual problem, so that's not bad at all. :)
doctornull 6 Jan, 2022 @ 6:46am 
BTW here's one of the best current starts I've seen generated:

https://i.imgur.com/4E9uAo9.jpg
corsairmarks  [developer] 6 Jan, 2022 @ 7:15pm 
Looks like if I am willing to wait 1 day after game start, everything works as it should. Here's some sample log output:

[22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Losstran Peav for the One is Damsath [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Damsath neighbored Losstran Peav; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Klomebaston for the Three is Reshell [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Eriga neighbored Klomebaston; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Reshell neighbored Klomebaston; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Padjitauron neighbored Klomebaston; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Qa-Adash for the Four is Acculum [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Tureis neighbored Qa-Adash; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Acculum neighbored Qa-Adash; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Bythia neighbored Qa-Adash; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Takaros for the Two is Andrussa [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Orim neighbored Takaros; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Andrussa neighbored Takaros; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Kaus Borealis neighbored Takaros; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Sol neighbored Takaros; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Vategigun for the Regime of Vasgogg is Nowitoff [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Nowitoff neighbored Vategigun; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 249. jovian league wormhole exit from Tempestua for the Stormrider Conclave is Nikalor [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Matsonia neighbored Tempestua; removed hyperlane between them [22:08:20][effect_impl.cpp:19501]: [2200.1.1] Log command triggered from effect in file: events/jovian_league_events.txt line: 278. Nikalor neighbored Tempestua; removed hyperlane between them [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Losstran Peav for the One [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Klomebaston for the Three [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Qa-Adash for the Four [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Takaros for the Two [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Vategigun for the Regime of Vasgogg [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 434. origin_jovian_league.9 check for isolated stars systems/"clusters" created when isolating Tempestua for the Stormrider Conclave [22:08:32][effect_impl.cpp:19501]: [2200.1.2] Log command triggered from effect in file: events/jovian_league_events.txt line: 450. Matsonia was more than 10 jumps from Nikalor; adding hyperlane between them

Also, it looks like the game is willing to randomize more than 4 Jovian Leagues, but there must be something hard-coded to prevent more than one empire with the same start system from spawning (even when force-spawned). I am adding code to ensure it remains unlimited for random empires, which is the best I can do there.

I haven't pushed the changes to Steam just yet because I'm going to explore adding the suggested "Sol" variants.
Last edited by corsairmarks; 6 Jan, 2022 @ 7:16pm
doctornull 6 Jan, 2022 @ 8:20pm 
Nice, looking forward to it.
< >
Showing 1-12 of 12 comments
Per page: 1530 50