Skip to main content
Topic: Checking whether a way is diagonal (Read 3667 times) previous topic - next topic

Checking whether a way is diagonal

I am attempting to implement a feature in Experimental whereby the costs of maintaining diagonal ways are divided by 1.4 of that of standard ways, to give, with some degree of approximation, a scaled effect to match the fact that the revenues are calculated using the Euclidean distance rather than the Manhattan distance. One issue that I have yet to resolve, and on which I should appreciate some guidance from those who know the code better than I do, is how effectively to check whether a way is diagonal.

I did find some code in Standard that appeared to do that (looking a bit like this:

Code: [Select]
switch(ribi) {

case ribi_t::nordost:
if(from->get_neighbour(to, get_waytype(), koord::ost))
r1 = to->get_weg_ribi_unmasked(get_waytype());
if(from->get_neighbour(to, get_waytype(), koord::nord))
r2 = to->get_weg_ribi_unmasked(get_waytype());
diagonal =
(r1 == ribi_t::suedwest || r2 == ribi_t::suedwest) &&
r1 != ribi_t::nordwest &&
r2 != ribi_t::suedost;
break;

case ribi_t::suedost:
if(from->get_neighbour(to, get_waytype(), koord::ost))
r1 = to->get_weg_ribi_unmasked(get_waytype());
if(from->get_neighbour(to, get_waytype(), koord::sued))
r2 = to->get_weg_ribi_unmasked(get_waytype());
diagonal =
(r1 == ribi_t::nordwest || r2 == ribi_t::nordwest) &&
r1 != ribi_t::suedwest &&
r2 != ribi_t::nordost;
break;

case ribi_t::nordwest:
if(from->get_neighbour(to, get_waytype(), koord::west))
r1 = to->get_weg_ribi_unmasked(get_waytype());
if(from->get_neighbour(to, get_waytype(), koord::nord))
r2 = to->get_weg_ribi_unmasked(get_waytype());
diagonal =
(r1 == ribi_t::suedost || r2 == ribi_t::suedost) &&
r1 != ribi_t::nordost &&
r2 != ribi_t::suedwest;
break;

case ribi_t::suedwest:
if(from->get_neighbour(to, get_waytype(), koord::west))
r1 = to->get_weg_ribi_unmasked(get_waytype());
if(from->get_neighbour(to, get_waytype(), koord::sued))
r2 = to->get_weg_ribi_unmasked(get_waytype());
diagonal =
(r1 == ribi_t::nordost || r2 == ribi_t::nordost) &&
r1 != ribi_t::suedost &&
r2 != ribi_t::nordwest;
break;

), which I broke out into its own method and made "diagonal" a member of the cl****, but I could not get "ribi" to be anything other than 0 when called; it is also a little difficult to know when to call this method (calling it in "init()" makes for excessive loading times, and "ribi" is not intialised at that stage in any case). Does anyone have any thoughts on how to approach this? Any input would be much appreciated.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

 

Re: Checking whether a way is diagonal

Reply #1
At loading time it will fail, since the way in question are very likely not loading. You could check at run time, whether the tile has a daigonal imgae (but there are ways without diagonal images). Thus best is a diagonal flag, that is set each time by laden_abschliessen().

Re: Checking whether a way is diagonal

Reply #2
Prissi,

thank you - that seems to work in part. However, I find that it only works when loading ways from a saved game: this is not triggered when laying new ways. What would be the best way of setting the flag for newly laid ways? Thank you again.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Re: Checking whether a way is diagonal

Reply #3
why not do this in void weg_t::calc_bild() ?
Parsley, sage, rosemary, and maggikraut.

Re: Checking whether a way is diagonal

Reply #4
Dwachs,

I've already put a call to the diagonal checking method in there, but, for some reason, that method is never actually called - is it a virtual method over-ridden in all the derived cl****es?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Re: Checking whether a way is diagonal

Reply #5
 ??? weg_t::calc_bild() has to be called very often: after loading, rotating etc.
Parsley, sage, rosemary, and maggikraut.

Re: Checking whether a way is diagonal

Reply #6
Dwachs,

aha - I have found the problem! laden_abschliessen() is not called when a new way is built: it is only called when a way is loaded. The following change to grund.cc means that I can set the diagonal status only in laden_abschliessen() and have it work on reloading as well as for new builds:

Code: [Select]
// just add the cost
if(sp && !ist_w****er()) {
- sp->add_maintenance( weg->get_besch()->get_wartung());
weg->set_besitzer( sp );
+ weg->laden_abschliessen();
}
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Re: Checking whether a way is diagonal

Reply #7
I find this to be a break of logic. "laden_abschliessen" means more or less "post_loading_calculations" and should only be called after loading a game.

If there this common code for another action, like building a way, the common code should be moved into a new method, maybe called "calc_diagonal_flags", and called from both "laden_abschliessen" and the place that you quoted in your message.

Method names should not mislead future developers.

Re: Checking whether a way is diagonal

Reply #8
Hajo,

ahh, thank you for the clarification. I shall have to change that - not knowing German, the intention of "laden_abschliessen" was not clear.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Re: Checking whether a way is diagonal

Reply #9
I had some hope that more and more of the could would be translated, but it seems some names, particularly the virtual methods, are very persistent.

If there are questions, I'll be glad to help out :)