The International Simutrans Forum

 

Author Topic: Diverse jamespetts questions  (Read 8592 times)

0 Members and 1 Guest are viewing this topic.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Diverse jamespetts questions
« on: December 06, 2008, 05:26:49 PM »
In the simvehikel.cc file, what unit of distance does the field, "long dist" measure? Kilometres? Tiles? Chains? Furlongs...?

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 10828
  • Languages: De,EN,JP
Re: Units of distance?
« Reply #1 on: December 06, 2008, 08:25:51 PM »
The only distance simutrans uses are tiles in Manhatten distance.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Units of distance?
« Reply #2 on: December 06, 2008, 08:35:30 PM »
The only distance simutrans uses are tiles in Manhatten distance.

Thank you - most helpful :-)

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Diverse jamespetts questions
« Reply #3 on: December 07, 2008, 10:08:36 PM »
I am trying to write a patch to increase maintenance costs for obsolete vehicles (see here for details), but I cannot for the life of me find where in the code the maintenance costs per vehicle are obtained.

I have found a method in simconvoi.cc called "get_running_cost()", which calls an accessor method called "gib_betriebskosten()", but, although I can find lots of other references to "gib_betriebskosten()", I cannot find the actual method definition anywhere. I am guessing that "gib_betriebskosten()" reads the basic maintenance cost of a vehicle from a table, which itself was read from a pak file. If gib_betriebskosten() is in the vehicle ("vehikel_t") class, then I could add code to check whether the vehicle is currently obsolete, and return a higher value if it is, but I cannot find that method to add code to it! (The alternative, if gib_betriebskosten() is not in the vehikel_t class, is to alter the get_running_cost() method, but that risks penalising the entire convoy for the obsolescence of one of its vehicles if the coding is done simply, or adding a lot of complexity and function to a method that looks as if it is meant to be simple if not). Can anybody assist?

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Divers jamespetts questions
« Reply #4 on: December 07, 2008, 11:31:16 PM »
As explained here, I am trying to develop a patch to increase maintenance costs of obsolete vehicles (and to do so somewhat gradually, instead of imposing a huge penalty the moment that they become obsolete). I wrote some code (in the simconvoi.cc file) to try to acheive this, but it does not seem to work: for some reason, the line:

Code: [Select]
if(fahr[i]->gib_besch()->is_retired(month_now)  &&  welt->use_timeline())

never evaluates to true (even when "&& welt->use_timeline()" is removed). I have reproduced the code in question below. Any ideas as to how to get it to work would be most welcome.

Code: [Select]
convoi_t::get_running_cost() const
{
sint32 running_cost = 0;
sint32 vehicle_running_cost = 0;
        const int month_now = welt->get_timeline_year_month();
for (unsigned i = 0; i<gib_vehikel_anzahl(); i++) { //"anzahl" = "number" (Babelfish)
vehicle_running_cost = fahr[i]->gib_betriebskosten();  //"get_operatingCost" (Google). "Fahr" = "Drive" (Babelfish)
if(fahr[i]->gib_besch()->is_retired(month_now)  &&  welt->use_timeline()) //If the vehicle is obsolete.
{
//Increase maintenance costs by amount specified in simuconf.tab.
//This system is ugly: if anyone can make a system that calculates this smoothly,
//rather than in steps, then so much the better.
sint32 extra_cost = 0;
float multiplier = 999;
if(!fahr[i]->gib_besch()->is_retired(month_now - 12)) //If has been obsolete for less than one year.
{
multiplier = (umgebung_t::obsolete_less_1_multiplier_percent / 100);
}
else if(!fahr[i]->gib_besch()->is_retired(month_now - 60)) //If has been obsolete for less than five years.
{
multiplier = (umgebung_t::obsolete_less_5_multiplier_percent / 100);
}
else if(!fahr[i]->gib_besch()->is_retired(month_now - 120)) //If has been obsolete for less than ten years.
{
multiplier = (umgebung_t::obsolete_less_10_multiplier_percent / 100);
}
else if(!fahr[i]->gib_besch()->is_retired(month_now - 240)) //If has been obsolete for less than twenty years.
{
multiplier = (umgebung_t::obsolete_less_20_multiplier_percent / 100);
}
else //If has been obsolete for more than 20 years
{
multiplier = (umgebung_t::obsolete_more_20_multiplier_percent / 100);
}
extra_cost = running_cost * multiplier;
vehicle_running_cost += extra_cost;
}
running_cost += vehicle_running_cost;
}
return running_cost;
}

Edit: Further testing has revealed that the real problem is that the get_running_cost() is not used by anything! I commented out all of the significant lines of code in that method, and the running costs behaved in exactly the same way as an unaltered version of Simutrans, downloaded as a binary. I am now extremely confused. Can anybody help?
« Last Edit: December 07, 2008, 11:56:54 PM by jamespetts »

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 10828
  • Languages: De,EN,JP
Re: Cannot get patch code to work - any ideas?
« Reply #5 on: December 08, 2008, 12:04:07 AM »
This is used, but only in the info windows, afaik. The running costs are calculated each step by each vehicle.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Cannot get patch code to work - any ideas?
« Reply #6 on: December 08, 2008, 06:46:41 AM »
This is used, but only in the info windows, afaik. The running costs are calculated each step by each vehicle.

Ahh, thank you. I'll put that code back to what it was, then. Where in the code is the running cost per vehicle calculated? Is it in the simvehikel.cc file?

Offline gerw

  • Coder/patcher
  • *
  • Posts: 618
Re: Cannot get patch code to work - any ideas?
« Reply #7 on: December 08, 2008, 01:23:52 PM »
Maybe you change gib_betriebskosten() in besch/vehikel_besch.h? You can add the current year as a parameter. If you do so, you don't need to change it at other places.

Edit:
The running cost are added (subtracted) in vehikel::hop(). This method is called everytime a vehikel changes the tile it is on.
« Last Edit: December 08, 2008, 01:26:16 PM by gerw »

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Cannot get patch code to work - any ideas?
« Reply #8 on: December 09, 2008, 12:21:56 AM »
Maybe you change gib_betriebskosten() in besch/vehikel_besch.h? You can add the current year as a parameter. If you do so, you don't need to change it at other places.

Edit:
The running cost are added (subtracted) in vehikel::hop(). This method is called everytime a vehikel changes the tile it is on.

Thank you very much - I will have a look at those methods when I get some time...

Offline gerw

  • Coder/patcher
  • *
  • Posts: 618
Re: Cannot get patch code to work - any ideas?
« Reply #9 on: December 09, 2008, 08:23:03 AM »
But ask prissi before editing gib_betriebskosten() if it's ok. In my opinion it is, since the new running costs should be used (and displayed) everywhere in the game. Or you add a new function get_current_running_costs. This is maybe even better.

You may also consider non-timeline games.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Cannot get patch code to work - any ideas?
« Reply #10 on: December 09, 2008, 03:32:23 PM »
But ask prissi before editing gib_betriebskosten() if it's ok. In my opinion it is, since the new running costs should be used (and displayed) everywhere in the game. Or you add a new function get_current_running_costs. This is maybe even better.

You may also consider non-timeline games.

As to non-timeline games, I can just add a condition to check whether there is a timeline being used before adding anything to the running costs of obsolete vehicles. I'll work on the patch when I have time and see how that goes.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Divers jamespetts questions
« Reply #11 on: December 10, 2008, 01:05:08 AM »
Thanks to those who helped me in this thread, I have managed to write a new patch for the vehicle maintenance costs based on obsolescence. I had to add a new file, vehikel_besch.cc, and replace the basic uint16 gib_betriebskosten() methid in vehikel_besch.h with a bare declaration, and then add the following code in vehikel_besch.cc:

Code: [Select]
#include "vehikel_besch.h"

uint16 vehikel_besch_t::gib_betriebskosten() const
{
//@author: jamespetts
//Running costs increased if obsolete.
if(!welt->use_timeline() || !is_retired(month_now)) return betriebskosten;
//Else
uint16 base_obsolete_running_costs = (umgebung_t::obsolete_running_cost_increase_percent / 100) * betriebskosten;
if((month_now - obsolete_date) >= (umgebung_t::obsolete_running_cost_increase_phase_years * 12)) return base_obsolete_running_costs;
//Else
//If not at end of phasing period, apply only a proportion of the obsolescence cost increase.
return ((base_obsolete_running_costs - betriebskosten) * ((month_now - obsolete_date) / (umgebung_t::obsolete_running_cost_increase_phase_years * 12)) + betriebskosten;
}

Now, when I compile, I get the following errors that I am having trouble understanding or debugging:

Quote
1>ai_goods.obj : error LNK2001: unresolved external symbol "public: unsigned short __thiscall vehikel_besch_t::gib_betriebskosten(void)const " (?gib_betriebskosten@vehikel_besch_t@@QBEGXZ)
1>F:\My Documents\Development\Simutrans\Sources\simutrans\trunk\Debug\Simutrans.exe : fatal error LNK1120: 1 unresolved externals

Those are the only errors that I get. I should be very grateful for any assistance.

Offline wernieman

  • Devotees (Inactive)
  • *
  • Posts: 713
    • Werniemans-Webside (only German)
Re: Cannot get new patch to compile
« Reply #12 on: December 10, 2008, 07:39:26 AM »
can you give me the full patch?

Offline gerw

  • Coder/patcher
  • *
  • Posts: 618
Re: Cannot get new patch to compile
« Reply #13 on: December 10, 2008, 08:59:35 AM »
I think your function vehikel_besch_t::gib_betriebskosten() doesn't know month_now. You also have to include ../dataobj/umgebung.h. But I wonder, that the error occur while linking and not while compiling.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Cannot get new patch to compile
« Reply #14 on: December 10, 2008, 09:10:04 AM »
can you give me the full patch?

I have tried, but, for some inexplicable reason, umgebung.h will not add itself to the patch: I get an "inconsistent line ending styles" error. Do you have any idea what I can do about this?

Offline gerw

  • Coder/patcher
  • *
  • Posts: 618
Re: Cannot get new patch to compile
« Reply #15 on: December 10, 2008, 09:13:19 AM »
I have tried, but, for some inexplicable reason, umgebung.h will not add itself to the patch: I get an "inconsistent line ending styles" error. Do you have any idea what I can do about this?
Windows and linux uses different line ending characters. Have a look at http://en.wikipedia.org/wiki/Newline#Common_problems. Maybe 'diff' is confused by this.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Cannot get new patch to compile
« Reply #16 on: December 10, 2008, 09:34:53 PM »
Thank you very much - I have now been able to get it to work, after much tinkering with different sorts of text encoding, although some of the German characters in the code comments have now turned peculiar. The patch attached deals both with the speed bonus modification for local transport described here, and the increased maintenance costs for obsolete vehicles (they are strongly linked in gameplay terms: the first patch would, as Prissi pointed out, cause problems without the second). I also attach an example simuconf.tab, showing the new settings implemented with their default values.

I should be very grateful if somebody could take a look at this and tell me why the new code in vehikel_besch.h and the entirely new vehikel_besch.cc file are stopping the program from linking properly, even though it compiles. Thank you all for your help so far.

Offline isidoro

  • Devotee
  • *
  • Posts: 1142
Re: Cannot get new patch to compile
« Reply #17 on: December 11, 2008, 12:51:35 AM »
The problem is that you have not included vehikel_besch.cc in the project and, thus, the object file is not compiled (you can check that: for all cc files there is an object file, except for that).  When the linker tries to resolve the address of the function inside that file, it cannot find it.

By the way, there are problems with three characters added at the beginning of dataobj/umgebung.h that prevent your patch to compile with gcc (0xEF,0xBB,0xBF).


Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Divers jamespetts questions
« Reply #18 on: December 14, 2008, 03:34:53 PM »
I am interested to look at the part of the code dealing with the generation of passengers, and how their destinations are chosen, but I cannot immediately find what part of the code handles that. At which file should I look to find the code for that?

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 10828
  • Languages: De,EN,JP
Re: Passenger generation?
« Reply #19 on: December 14, 2008, 03:47:03 PM »
Simcity.cc, step_passagiere()

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Passenger generation?
« Reply #20 on: December 14, 2008, 04:10:23 PM »
Simcity.cc, step_passagiere()

Thank you very much - I will have a look!

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Coding trouble: assert failure on deletion of pointer
« Reply #21 on: December 26, 2008, 07:13:30 PM »
I am trying to code a smooth declaration routine (as discussed here) using an array of pointers to the tiles that a vehicle will be entering in the future steps of its route; however, I have run into a problem that I am having great difficulty understanding, let alone solving. If I simply obtain a pointer to an existing koord3d object, those objects will often have been deleted by the time that the code next comes to use them, and so an exception will be thrown. I solved that by using a the new keyword to generate new memory addresses for all the pointers so that deletion of the original pointers does not cause problems. However, if I just left it at that, a memory leak would be created, so I then try to use the delete keyword to delete the elements of the array that are not going to be used. However, whenever I do that, I get a cryptic runtime "assertion failure", which traces back to the delete keyword. I have spent hours trying to understand what the problem is, to no avail. The runtime error is encountered whenever either of the two delete keywords are reached in the code in the following extract. I should be extremely grateful for any assistance.

Code: [Select]
void
vehikel_t::set_lookahead()
{
route_t *route = cnv->get_route();
int max_lookahead = (route->gib_max_n() - route_index);
const koord3d* old_zero;
if(lookahead[0] != lookahead[15])
{
old_zero = lookahead[0];
}
else
{
old_zero = NULL;
}
for(int i = 0; i < 15; i++)
{
uint8 j = i + 1;
int limit = (max_lookahead < 14) ? max_lookahead : 14;
if(i <= max_lookahead)
{
if(lookahead[j] == lookahead[15]) //If next item in array is empty
{
if(lookahead[i] != lookahead[15])
{
delete lookahead[i];
}
const koord3d *tmp;
tmp = new const koord3d;
tmp = &route->position_bei(route_index + i);
//const koord3d tmp = route->position_bei(route_index + i);
//lookahead[i] = &tmp;
lookahead[i] = tmp;
}
else  //If next item in array has something in it, shunt it up one.
{
lookahead[i] = lookahead[j];
}
}
else
{
lookahead[i] = lookahead[15];
}
}
delete old_zero;
}

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 10828
  • Languages: De,EN,JP
Re: Coding trouble: assert failure on deletion of pointer
« Reply #22 on: December 26, 2008, 07:31:13 PM »
You have to look up each tile again, when you need it, directly from route. There is no other good way of achieving it (but it is costly of course, timewise).

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Coding trouble: assert failure on deletion of pointer
« Reply #23 on: December 26, 2008, 08:09:41 PM »
You have to look up each tile again, when you need it, directly from route. There is no other good way of achieving it (but it is costly of course, timewise).

Why do they have to be looked up again, instead of being stored in an array?

Offline prissi

  • Developer
  • Administrator
  • *
  • Posts: 10828
  • Languages: De,EN,JP
Re: Coding trouble: assert failure on deletion of pointer
« Reply #24 on: December 26, 2008, 10:10:47 PM »
Because it can changed by user interaction or choose signals any time. Although, if you hook this up to the block reservation for trains, then you are noticed. But not for cars.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Coding trouble: assert failure on deletion of pointer
« Reply #25 on: December 26, 2008, 10:20:55 PM »
Because it can changed by user interaction or choose signals any time. Although, if you hook this up to the block reservation for trains, then you are noticed. But not for cars.

Ahh, I see. Thank you. Hmm. I have spent a long time to-day trying to get smooth vehicle slowing, and I seem to have difficulties at every step. Even if I recalculate the whole thing every step, I end up with bizarre behaviour of vehicles sliding sideways on the track.

Edit: I have solved the sideways movement, but, even though I am re-setting the array with each hop, I am still unable to take the values directly from the route->position_bei function like this:

Code: [Select]
const koord3d tmp = route->position_bei(route_index + i);
lookahead[i] = &tmp;

without causing an access violation whenever all the koord3d values get cleared somewhere, so I still have to do this:

Code: [Select]
const koord3d *tmp;
tmp = new const koord3d;
tmp = &route->position_bei(route_index + i);
lookahead[i] = tmp;

which means that I assign new memory for each hop; but I still get an assert error (from MFC, I think - it's not in a Simutrans source code file) when I try to delete it. Worse, when I ignore the assert error, I get an access violation, but the debugger won't tell me what line of code that it's in! So, I either get an access violation, an assert error or a memory leak.

Edit 2: Never mind - I found that it works if I simply remove the "tmp = new const koord3d;" statement... Would there be a way of testing to see whether or not a choose signal or user has modified the route, so that the program only have to re-assemble the array if necessary?
« Last Edit: December 26, 2008, 11:18:53 PM by jamespetts »

Offline isidoro

  • Devotee
  • *
  • Posts: 1142
Re: Coding trouble: assert failure on deletion of pointer
« Reply #26 on: December 28, 2008, 03:25:03 AM »
I see some potential source of errors in your code:
  • Are you sure that all vehicles have a valid convoi?  In convoi_t, it reads "cnv != NULL falls das vehikel zu einem Convoi gehoert"
  • The same question for route. Is always a valid pointer?
  • I cannot understand your code without further comments, but giving a value to tmp and, afterwards, overwriting that value with the return value of route->position_bei makes no sense.  Furthermore, that memory is lost.  When you delete, you delete the original object.
  • Keeping a pointer of dynamic memory across calls to your function is not very safe.  The owner of that memory can delete it when you regain control.  You should do a copy but, as you state, that copy can contain a stale route and be useless when trying to use it again.

Hope it helps.

Offline jamespetts

  • Simutrans-Extended project coordinator
  • Administrator
  • *
  • Posts: 20918
  • Cake baker
    • Bridgewater-Brunel
  • Languages: EN
Re: Coding trouble: assert failure on deletion of pointer
« Reply #27 on: December 28, 2008, 02:11:08 PM »
Isidoro,

thank you very much for your feedback. I have entirely removed the "new" statement, as I have realised that that was redundant. The difficulty is that there does not appear be a method for copying koord3d objects, so setting a new pointer is not very useful. The idea is that I will use my new fixed_list template class instead of the array that I have been using, and clear it whenever the route is re-determined. Then, using the size property of the list, I can make sure that I never try to access a deprecated element.