Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: setting for more flexible town spacing #7745

Closed
wants to merge 1 commit into from

Conversation

Eddi-z
Copy link
Contributor

@Eddi-z Eddi-z commented Sep 16, 2019

This is an old patch i found on my disk, from around 2011, that i don't remember how complete it was

It allows more flexibility in specifying road layouts by setting the minimum distance between parallel roads in either a "natural" (randomized) or a "grid" (fixed) pattern

during rebasing, i kinda fudged the AI bits, which were not present in the original patch. there probably needs to be some kind of compatibility layer, which i have no clue how it works

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Sep 17, 2019

a screenshot made with a simpler version of the patch:
screenshot1

old forum discussion: https://www.tt-forums.net/viewtopic.php?p=982943#p982943

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Sep 17, 2019

What's definitely missing is a rework of the scenario editor gui for selecting road layout

@nielsmh
Copy link
Contributor

nielsmh commented Sep 17, 2019

This is totally an OpenTTD 2.0 feature (by which I mean we should merge it ASAP and call the version 2.0)

@andythenorth
Copy link
Contributor

andythenorth commented Sep 18, 2019

Tested with min 4, max 6.

Results from a few random new maps are compelling. I didn't run a long game yet to see results as towns grow.

Observations

  • looks better IMO
  • doesn't create enough gaps to trivially build rail stations or smaller airports in towns (I think this would be useful, but maybe hard to achieve)
  • does create enough gaps to ease building tunnels, bridges, rails, RV depots etc in towns
  • I noticed in rare occasions, 1x1 buildings placed with no adjacent road tile, I wasn't sure if that was intended

Related idea, it would be helpful if towns built more bridges of n+1 or n+2 length instead of n. Town bridges tend to be a constraint that block potential routes, and they're non-removable. Creating bridge spans over empty tiles allows routing under the bridge, makes river corridors a viable route into towns. Case could even be made that it's realistic (flood arches) 😺 I put a crude 'delta + 1' hack into GrowTownWithBridge, which works for NE-SW direction only, appears to break bridges for other directions, out of my depth here. Would be a different PR anyway.
bridge_n_plus_1

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Sep 18, 2019

* I noticed in rare occasions, 1x1 buildings placed with no adjacent road tile, I wasn't sure if that was intended

that does not sound like anything this patch should cause, so this is likely existing master behavior

@nielsmh
Copy link
Contributor

nielsmh commented Sep 18, 2019

I've seen mentioned that if a 2x2, 2x1, or 1x2 building is replaced with a 1x1 building, the 1x1 building is always in the top corner of the replaced building, which may be away from a road.

@andythenorth
Copy link
Contributor

I've seen mentioned that if a 2x2, 2x1, or 1x2 building is replaced with a 1x1 building, the 1x1 building is always in the top corner of the replaced building, which may be away from a road.

Non-issue for this PR then 👍

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Sep 18, 2019

Note that i am touching some code containing calls to "GrowTownWithExtraHouse", where "extra house" means "fill in the middle of a 3x3 grid", which would not directly touch any roads. IIRC this requires roads on at least 3 sides, 1 tile away.

case TL_3X3_GRID:
if ((grid_pos.x & 3) < 2 || (grid_pos.y & 3) < 2) return false;
case TL_GRID:
grid_pos.x = Mod(grid_pos.x, t->spacing + 1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of this weird mod thing. Why is it that % doesn't work / produce desirable results ?

Copy link
Contributor Author

@Eddi-z Eddi-z Nov 2, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

% rounds towards 0, whereas this Mod function rounds towards -infinity, which does different things for negative numbers.

using plain % would thus create special cases

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a lambda be used to avoid old c-style library functions being added for this trivial esoteric case?

@andythenorth
Copy link
Contributor

andythenorth commented Nov 2, 2019

I experimentally increased MAX_TOWN_SPACING to 12.

I think it's of benefit when player wants grid layouts with space for infrastructure. Examples attached showing grids with min 8 and max 12. There were no really pathological examples when I tested.

Obviously the centre of towns looks odd, as large buildings are adjacent to empty green space. But that can be avoided by choosing lower grid spacing. Player choice eh.

For the natural town layout, increasing the grid spacing is a neutral choice. Towns work fine, there's no real gameplay benefit for spacing 8 or 12 compared to 6, and no pathological effects.

For the grid layouts, the improvement I see is for players who want to build metro / urban train networks, where the empty areas can accommodate short stations and tunnel entrances etc.

7745_3

7745_1

7745_2

@LordAro LordAro added this to the 1.11.0 milestone Nov 23, 2019
@floodious
Copy link

floodious commented Jan 7, 2020

This is all very interesting stuff openttd is in my opinion/experience desperately in need of.

Issue with single-scope planning

At current larger grid divisions there is no way for a town to "fill in" the space between major divisions. The buildings only appear within fixed distance from roads. So it requires some hierarchical sub-division planning to fill those voids as neighborhoods, parks or natural (forest, ...) spaces.

Realism

Realistic city blocks are almost never square, but rather tend to be strongly (10 to 1 or more?) biased
in one dimension and rectangular. For example there are two common older mid 20th century North American layouts, very abstractly sub-dividing them into whether alleyways "service/access lanes" are placed between roads, streets and avenues.

These decisions are almost always up to local municipalities... but generally speaking you start out with cheap-to-build roads dividing larger sections. These long-straight roads snake around large obstacles and connect industries and farms to population centers.

The municipality then decides on a grid-filling layout which might include some specification for high-traffic avenues or mid-block service lanes dividing different classes of city blocks. (Industry, commercial, residential at the most simple abstraction.)

Examples from the real world (NA, different places in Europe or elsewhere have different styles by region.)

https://www.vox.com/2016/11/14/13275486/streets-roads-avenues-names-reasons

Here's an example from "Garden City" in Detroit, MI (no alleyways) (12x2 blocks.)
https://www.google.com/maps/@42.3160081,-83.3396002,2483m/data=!3m1!1e3

Here's Corvallis, OR (alleyways) (looks like 2x6 blocks with some double-width properties.)
https://www.google.com/maps/@44.562329,-123.2688142,266m/data=!3m1!1e3

A residential layout may include straight rectangular blocks, or more modern suburbs tend to be built with heavy (double one-way) commercial avenues dividing main streets on a coarse grid and smaller court or place lanes within smaller neighbourhoods with cul-de-sacs and similar. This is because the large-scale rectangular grids look awful and tend to produce traffic and other problems (service distribution, crime, large-scale planning issues, ...)

Practical implementation for openTTD

While this goes really beyond over complicated for something like openttd, it's rare to see endless grids of perfectly square blocks outside larger grids of streets, within larger grids of avenues. So in the very least it would make sense to have multiple layers of planning... in the least a plan might include specific dimensions for residential and commercial blocks rather than a single dimension and single grid. From some fixed plan for the larger neighborhood/district grid (X x Y) various sub-types could be selected randomly (2/3rd common, 1/12th * 4 rare?) for rows or columns within each.

Due to limited by-default selection of road type in openTTD, features like parkways, avenues and alleyways are all limited to being represented by one road type. So for that reason combined with the fixed tile grid it does not make sense to feature high-res details like alleyways.

A practical example might be:

  • block = 6+1 (ave) x 2+1 (street) = 7x3 (tiles)
  • neighbourhood = 2x2 (blocks) = 14x6 (tiles)
  • section = 2x2 (neighbourhoods) = 28x12 (tiles)

The lanes/roads would then be initially run out at a grid spacing of 28x12. Each town would begin with a single road intersection in the center of 4 sections, 16 neighbourhoods and 64 blocks.

(... removed some vaguely related rambling about neighbourhood and block sub-types.)

Even with three simple hierarchical layers I can tell it would be easier to understand with some graphical representation... such discussion might have a better place to occur, I'd like to come back to this post and move 99% of it to a feature-request or planning thread instead linking both ways. That improved description of the idea would get some bitmaps to visualize my descriptions.

Many municipalities develop very slowly over time, where sections of such a plan are added one-by-one in single neighbourhood units, or at larger scales towns = "districts". From a planing perspective these blocks are typically fit around obstructions like hills or cliffs (any change in Z in openttd.) The origin of the large-scale dividing roads in many plans and the source of names also come from historic destinations like "Timothy Station Rd." or "Olhamm Farm Rd."

That natural evolutionary process is way out of the scope of openttd currently, so the question is how to produce highly-playable approximately real looking results without such a process.

Points of reference

While there is no definite scale in openttd, it is possible to come up with a range of practical scales. A typical lane/street is approximately 20 meters wide, so as a very rough starting point based upon roads we can assume 1 tile = 20 x 20 meters. The scale for buildings on a tile is then weird since a small residential lot is generally rectangular such as 15 x 40 meters, but this is definitely close enough assuming no driveway, no garden space and such 15 x 15 sized homes are typical. That would be 225 sq meters or near 2400 sq feet.

So with confirmation of the rough house + road scale at 20 meter units, we can say a 4096 map edge would be 81.92 kilometers, meaning a 4k x 4k map could reasonably approximate the whole of the city of Detroit if everything were at perfect 90 degree angles.

Such a region could contain 798915 7x3 city blocks, 199728 neighbourhoods and 49932 sections. 7 x 3 x 2 x 2 x 2 x 2 = 336, 4096^2 = 16777216, 16777216 / 336 = 49932.

So this verifies that the 4k scale is way beyond enough to contain towns with such "realistic" block sizes.

SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_2x2, "ROAD_LAYOUT_2x2");
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_3x3, "ROAD_LAYOUT_3x3");
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_NATURAL, "ROAD_LAYOUT_NATURAL");
SQGSTown.DefSQConst(engine, ScriptTown::ROAD_LAYOUT_GRID, "ROAD_LAYOUT_GRID");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps needs some compat.nut stuff for Squirrel, to allow creating and querying towns with the old interface.

@TrueBrain TrueBrain added candidate: yes This Pull Request is a candidate for being merged size: large This Pull Request is large in size; review will take a while labels Dec 14, 2020
@TrueBrain TrueBrain added candidate: probably not This Pull Request will most likely be closed soon and removed candidate: yes This Pull Request is a candidate for being merged labels Dec 24, 2020
@TrueBrain
Copy link
Member

We have talked this over a few times now, and I keep coming back to: I really like what this PR does, but I do not think this is the right solution for vanilla OpenTTD.

The thing is, we now make the distance of the grids a setting; it looks cool, but as the comments show, immediately new ideas pop up to improve towns further. And this keeps piling up. Up till what point should this be done hard-coded in C++, and where do we say: someone should make this possible in a "mod" (either GameScript or NewGRF or something new; I have not given that any thought). So despite me liking the result, and it somewhat cleans up some parts of the code too, I think it is the wrong move for OpenTTD to take.

Unless one of the developers thinks otherwise about this, I am tempted to close this Pull Request. I hope someone says: I am going to make this moddable, as that would be straight-up awesome. People can then just invent their own algorithm to grow nice looking towns .. can't wait to see that result :D

@floodious
Copy link

floodious commented Dec 25, 2020

I disagree regarding whether towns are a core element of vanilla OpenTTD. I would argue that towns do not work, never worked and the current implementation and the original TT code upon which it was based were temporary stopgap solutions that were never replaced with a working solution.

In that respect the current stopgap can be considered a void. Towns are not currently a functional element of OpenTTD and detract from an enjoyable game more than they add. Industry to industry transport is more or less functional and despite notable issues it works. Transport from an industry to the border of a town (goods, ...) more or less works but can be troublesome when the single building accepting goods, mail or passengers is arbitrarily moved to the opposite side of town by the current code.

Mail and passenger transport between towns is barely functional with no sensible mechanism to reserve space for tracks and construct efficient transportation networks (road, rail, ...) in conjunction with continuous interference from the town AI.

edit: An attempt to clarify;
What I mean by this is that if this is not the "right solution for OpenTTD", what is? First, decide whether improving the currently dysfunctional town system is a goal, true or false? Second the question is: is this improvement to the existing code and new functionality a valid step toward a better implementation?

I would argue that yes, such small improvements are exactly the right solution for OpenTTD unless a specific objection can be made to some part of this implementation. Outright rejection of any improvement whatsoever is also possible.

@floodious
Copy link

Towns as they are currently serve one significant purpose that I'm aware of: the base for industries.

The location of a town, roadways constructed by the town, buildings and industries for the most part have no logic applied to ensure their placement makes sense. A town can be constructed on a sharp ledge on the side of a slope and will merrily construct sheer roadways and houses on cliff edges with no planning whatsoever. Various industries are likewise only implementing minimal logic routines such as that used for farms.

The real threat of admitting the core issue with the structure of towns is that they are a void which serves as the foundation for the entire game.

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Dec 25, 2020

someone should make this possible in a "mod" (either GameScript or NewGRF or something new; I have not given that any thought).

Actually, we did discuss this before.
the irc log timestamp i have for that discussion is "[Saturday, 13. April 2019] [21:37:03 CEST]", but the webster logs for that day don't load, and i've not found any reference of your logs replacement going live yet, so i can't link it.

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Dec 25, 2020

Putting aside the parts about "we should do this completely differently", one particular part of this PR that i was never content with is the following:

  • if you select grid, you get
    • min spacing = setting
    • max spacing = setting
    • avg spacing = setting
  • if you select natural, you get
    • min spacing = setting
    • max spacing = 2 * setting
    • avg spacing = 1.5 * setting

this discrepancy gets annoying if you want to mix grid and natural town layouts

if i were to work on this PR (which i won't, because you said you're going to reject it), i would probably try to change this to:

  • min spacing = 2/3 * setting
  • max spacing = 4/3 * setting
  • avg spacing = setting

although dividing by 3 is always a bit awkward.

this should make it less likely that you want different setting values for grid vs natural

@JGRennison
Copy link
Contributor

Actually, we did discuss this before.
the irc log timestamp i have for that discussion is "[Saturday, 13. April 2019] [21:37:03 CEST]", but the webster logs for that day don't load, and i've not found any reference of your logs replacement going live yet, so i can't link it.

This site tends to be more reliable than webster.
https://irclogs.thegrebs.com/openttd/2019/04/13#15:37

@floodious
Copy link

Discussion of a modular AI for towns seems quite ridiculous without a working implementation to demo the idea. I would note the lack of a fully functional general AI for OpenTTD despite the modular NoAI system having existed for over a decade.

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Dec 25, 2020

Concerning "which part should be C++, and which part mod", this is highly dependent on how we are going to achieve modability, but i feel like the moddable parts should be higher level, like placing "city districts" or something, and a few basic road placement algorithms should be provided in C++, with possibility to implement custom algorithms

@floodious
Copy link

floodious commented Dec 25, 2020

Concerning "which part should be C++, and which part mod", this is highly dependent on how we are going to achieve modability, but i feel like the moddable parts should be higher level, like placing "city districts" or something, and a few basic road placement algorithms should be provided in C++, with possibility to implement custom algorithms

Good modular design provides for a reference implementation as a module using the same system as any other module. This acts to verify the modular interface capabilities by application.

How one might go about this task depends upon particularities; nonetheless a functional implementation is required first to determine the requirements of the modular interface. That is to say first you make it work, then you modularize it, then repeat, recurse and so forth.

@floodious
Copy link

In other words, customization or doing things differently hardly matters when there is no working implementation to change in the first place.

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Dec 25, 2020

Good modular design provides for a reference implementation as a module using the same system as any other module.

Well. I could write an essay or a dozen about how a complex codebase with lots of legacy has problems following "good design" principles.

one "legacy" conflict with this design principle is that there is a long standing policy that the game does not get bundled with "mods", even if they would pretty well serve as a "reference implementation". e.g. OpenGFX

the other problem is that, even if a modder can provide custom road layout algorithms, should they have to? someone that just wants to change high-level stuff like how the town reacts to player activity shouldn't have to be concerned where each and every piece of road goes, they should just be able to say "yeah, do whatever vanilla does"

@floodious
Copy link

That's a question about a town system that as of yet does not exist.

@Eddi-z
Copy link
Contributor Author

Eddi-z commented Dec 25, 2020

That's a question about a town system that as of yet does not exist.

what else do you think "design" is?

@floodious
Copy link

Well, from my point of view there is nothing to discuss regarding modularity. Yes, you're 100% correct with regard to primitive codebases being poorly designed and inflexible, difficult to maintain and impossible to modularize. Modern c++ implementations are fully modular and moving the OpenTTD codebase toward this is I agree something that should be a top priority.

@floodious
Copy link

We have talked this over a few times now, and I keep coming back to: I really like what this PR does, but I do not think this is the right solution for vanilla OpenTTD.

The thing is, we now make the distance of the grids a setting; it looks cool, but as the comments show, immediately new ideas pop up to improve towns further. And this keeps piling up. Up till what point should this be done hard-coded in C++, and where do we say: someone should make this possible in a "mod"

I think this concern with "piling up" is an apparent (although false) conflict between maintaining the original implementation and making it more flexible, adding options and eventually the full modularization of it. So in that respect it must be carefully measured in terms of whether this pull request improves the original code whilst maintaining its original function, or is merely an additional functionality that does not improve the original code.

With that in mind I would point out the fact that the majority of the town AI is not original to begin with; nonetheless it is a valid concern to avoid piling on additions that make the code more complex rather than simplifying it and adding flexibility.

From what I can see this is entirely an improvement, it maintains the original functionality and does not add any excessive new functionality.

@TrueBrain
Copy link
Member

As mentioned earlier, and as no dev has come forth, I am going to close this PR for now.

Work for moddable town-layouts is slowly starting up, where the first few drafts of the concept have been made. So at least we have that to look forward to :)

As always, if any of the devs feel I am in the wrong of closing this PR, feel free to open up that dialog! I am just managing expectations here, to not let PRs open for years on end, where no dev wants to touch it; not fair to the author and not helpful for the community at large.

Nevertheless, as I have mentioned a few times already, I do like the result of this PR, so I do hope we can make it possible soon to implement similar behaviour :D Tnx for the work!

@TrueBrain TrueBrain closed this Dec 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
candidate: probably not This Pull Request will most likely be closed soon size: large This Pull Request is large in size; review will take a while
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants