Transport Tycoon Forums

The place to talk about Transport Tycoon
It is currently Fri May 24, 2013 7:49 am

All times are UTC




Post new topic Reply to topic  [ 38 posts ]  Go to page Previous  1, 2
Author Message
PostPosted: Mon Mar 19, 2012 6:39 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
I currently try to understand how management of vehicle orders in OpenTTD works. I found the enum below in order_type.h, and am trying to understand how the different order types are used during gameplay.

Specifically, my impression from reading the code is that the type of an order changes during gameplay, in particular between the states OT_LOADING and OT_LEAVESTATION, just by movement of the vehicle.

Question: Am I right concerning this, can anyone give me some sentences about
1. if and how orders change between these states of (my impression) a simple automaton
2. wether vehicle->current_order is really an instance from the OrderList, or just a copy of such an instance with updated state e.g. OT_LOADING
3. is interaction of the user in the order management GUI the only event that triggers changes of the order->dest attribute, or does it also change in the context of those state transitions?

Specifically, I am currently designing the integration of my newly introduced concept of Routes into the existing concept of Orders. My current idea is:
(i) Add a reference to a Route to the Order struct. It has the meaning that a vehicle uses that particular route while processing the order at hand. This is the necessary link for supporting TimeTables for Routes.
(ii) If and only if an Order has a Route (i.e. not INVALID_ROUTE), its dest attribute references a RouteNode. RouteNodes can store an id of a station or a depot, or alternatively a set of tiles. This gives me the possibility of (a) supporting tile sets in routes (see below), and (b) supporting multiple RouteNodes in huge stations, e.g. something like one section for long-distance trains, and one for the local trains, with different timetables.

(ii) means that if an Order uses the concept of Routes (it will be optional), the destination of the Order will be determined via the indirection of the RouteNode, but there will be no field in struct Order for that.

Alternatively, I might add a new variable route_node_id in struct Order, with meaning as above, which will partly (but only partly) store information redundant to the existing dest attribute.

For now I decided for the first option, but which one is better depends on the details of order management I not yet fully understood. Thus my hope that someone can write some sentences about this (as designing this the right way will be quite central for my patch...).

BTW, for more details on what I want to do read the first post in this thread, beside the fact that I dropped the concept of RouteEdges, it is still valid.

As for tile sets: I want to support them because I think they will be useful if routes intersect outside stations, and for updating timetable information independent from stations, e.g. at a place where trains meet on a one-track-line. Their semantics will be that I regard a tile set node as being passed if and only if the vehicle has touched at least one element in the tile set. It is no harm if it doesn´t touch any at all since this can be detected when it reaches the next order. Also note that routes can only intersect at route nodes.

Specifically, I do not want to touch routing at least in the scope of this patch, but this design maybe opens room for a routing algorithm which not only accepts stations / depots but also arbitrary sets of tiles as destinations.

Code:
/** Order types */
enum OrderType {
   OT_BEGIN         = 0,
   OT_NOTHING       = 0,
   OT_GOTO_STATION  = 1,
   OT_GOTO_DEPOT    = 2,
   OT_LOADING       = 3,
   OT_LEAVESTATION  = 4,
   OT_DUMMY         = 5,
   OT_GOTO_WAYPOINT = 6,
   OT_CONDITIONAL   = 7,
   OT_IMPLICIT     = 8,
   OT_END
};


Top
 Profile  
 
PostPosted: Mon Mar 19, 2012 11:55 pm 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 4576
Not in reply to your post.

What i imagine a "route" could be:
A vehicle-independent (partial) order list.

Example:
assume i have a large network, and pick two neighbouring passenger hub stations "A" and "B". The line between the two stations is single tracked, but has a passing point with a station "C" in the middle, and two waypoints directly at the beginning of the hub station junctions "ab" and "ba".

now i define a "Route AB" := A-ab-C-ba-B and a "Route BA" := B-ba-C-ab-A, and to define the order list of a train going from X to Y i could define it as "load at X" + "Route XA" + "Route AB" + "Route BY" + "unload at Y" + "Route YB" + "Route BA" + "Route AX".

to further complicate things i now have three use patterns for the route: "freight", "passenger" and "express", each one has its own timetable.

the freight pattern would read:
"A-ac": long travel time
"ac-C": long travel time
"C": long waiting time - no load and no unload [wait for faster train to pass]
"C-bc": long travel time
"bc-B": long travel time

the passenger pattern would read
"A-ac": medium travel time
"ac-C": medium travel time
"C": short waiting time [wait for opposite train]
"C-bc": medium travel time
"bc-B": medium travel time

the express pattern would read
"A-ac": short travel time
"ac-C": short travel time
"C": go via [no stop]
"C-bc": short travel time
"bc-B": short travel time

now i can get a station timetable for A and B, and arrange the train start times in a way that there will be no blocking at C, and the wait times can be minimized, without affecting the rest of the network too much.

In a second complification step i could now take a station like A, and the adjacent waypoints ab, az, ax and aw, and arrange the trains coming through the matching routes and lead them to specific platforms, so parallel trains do not block each other, and crossing trains get scheduled to different times.

now getting back to an older question:
ic111 wrote:
Quote:
also i think a timetable should have at least two entries for the time, one "raw" travel/loading time, and one "buffer" time. an optional "autoseparation" would then only be adjusting the "buffer" times, an "autofill" would put the "raw" time as if it were always travelling at full speed, and the "buffer" time with whatever time it spent wating on signals.


I don´t fully understand your point here. Questions:

let me try to explain my thoughts:
Quote:
- Could you give some simple example for making clear why you would need those two times?

the idea is that the "raw" time is the absolute lower bound of physical possibilities, if a train could run free without any interruptions. no amount of timetable fiddling can change that, so any "autoadjusting" feature would leave these alone. on the other hand it can use these times as a guide for an upper bound, so the "padded" round trip time is never more than factor X of this lower bound, it gives up autoadjusting after that. (the current autoseparation patch has big problems with traffic jams, where the adjustment of the wait times due to lateness increases the effect, and causes even worse jams)
Quote:
- Could you define what you expect from an autofill feature?

imho there should be two ways to "autofill", a "static" autofill which only looks at the stations (and depending on how elaborate it is, the pathfinder between these stations), and calculates the timetable instantly on pressing a button. and a "dynamic" autofill, which behaves like currently, i.e. it measures the distance actually travelled and the time it has actually taken, through one roundtrip. the "raw" entry would then be filled by "distance/max speed" and the "buffer" entry would be the difference between "actual time" and "raw time" [this should never be <0]

in case of "dynamic" autofill, the amount of "buffer" travel time can be used as a diagnosis tool where the blocking of vehicles could be reduced.
Quote:
- Could you define what you expect from an autoseparation feature?

autoseparation is a complicated matter, different people want it to do different things. in the easiest case, it should provide a "fire and forget" way to prevent vehicles of a shared schedule from lumping up and all going at the same time, while the route is empty the rest of the time.

i present here three different ways how that could be achieved:
version 1: this method does not touch the timetable at all. only the timetable roundtrip time is calculated, and divided by the number of vehicles, then the start time is adjusted so that spacing is ensured. the user is required to ensure that the timetable has enough buffer times to catch up lateness. (this is roughly how "slim timetable separation" works)

version 2: this method adjusts the buffer time, in order to handle lateness due to traffic jam etc. when a vehicle is frequently late, the buffer time is increased to space out the vehicles more. (this is how the "original" autoseparation works) as an improvement, using the "raw" and "buffer" times, an upper limit can be specified, to prevent overcompensation. also, if the buffer time for a station is 0, this can mean "never adjust this time", so the user can specify at which stations the vehicles should wait (usually the end stations of a line)

version 3: this method additionally uses "synchronization points", where a vehicle has to arrive at/leave a station at a specific time, not only at a specific interval. this can help with single track lines, where the two opposing trains have to be at the switchover station at the same time, otherwise a train will be waiting unnecessarily, or it could synchronize separate lines for a cargodist network.
Quote:
Specifically, based on my understanding of an autoseparation feature, to what degree would the underlying problem be solved by a simple solution for manually defining offsets between vehicles as stated above?

as far as i understand you, that would be version 1 above. the advantage of that is that it is algorithmically very simple, the disadvantage is that it cannot react on vehicles being late.

_________________
You might not exactly be interested in Ferion, but if you are, have fun :)


Top
 Profile  
 
PostPosted: Tue Mar 20, 2012 6:24 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Quote:
What i imagine a "route" could be:
A vehicle-independent (partial) order list.

Example:
assume i have a large network, and pick two neighbouring passenger hub stations "A" and "B". The line between the two stations is single tracked, but has a passing point with a station "C" in the middle, and two waypoints directly at the beginning of the hub station junctions "ab" and "ba".

(...)


I think you in fact describe something I also have on my todo list for that patch, but which I omitted above because it is not that relevant for the questions I have to find answers for right now:

I am thinking about hierarchical timetables. I.e. there is a new order type OT_ORDERLIST, which means that at that point, the vehicle starts processing a sublist of orders stored in another timetable.

Remember that I intend to store order times in an absolute manner, vehicles (and orderlists for sublists, see below) then store an offset for such a timetable. A simple example for two vehicles on your line, which meet in C, would be:

Timetable 1:
Goto A, arrive 1st March, depart 5th March
Goto C, arrive 16th March, depart 20th March

Timetable 2:
Goto B, arrive 1st March, depart 5th March
Goto C, arrive 16th March, depart 20th March

Timetable 3:
Use Timetable 1, offset zero days
Use Timetable 2, offset 30 days

Vehicle 1: Use Timetable 3, offset zero days
Vehicle 2: Use Timetable 3, offset 30 days.

In the end, vehicle 2 arrives at A on March 31st (Timetable 1 says 1st March, Timetable 3 specifies an offset of zero days, vehicle 2 specifies an offset of 30 days).
On the way back, it will arrive in C on: 16th March plus 30 days plus 30 days = 15th May because Timetable 3 specifies an offset of 30 days for Timetable 2 and Vehicle 2 again specifies an offset of 30 days.

Of course, for such a short line it would be overengineerd, but in fact I think this should make using vehicles with long timetables and possibly on different lines in a longer roundtrip quite simple.

As far as I understand your point, this should solve the problems you sketched above.

Quote:
imho there should be two ways to "autofill", a "static" autofill which only looks at the stations (and depending on how elaborate it is, the pathfinder between these stations), and calculates the timetable instantly on pressing a button. and a "dynamic" autofill, which behaves like currently, i.e. it measures the distance actually travelled and the time it has actually taken, through one roundtrip. the "raw" entry would then be filled by "distance/max speed" and the "buffer" entry would be the difference between "actual time" and "raw time" [this should never be <0]

in case of "dynamic" autofill, the amount of "buffer" travel time can be used as a diagnosis tool where the blocking of vehicles could be reduced.


Hm, I think surprising traffic jams are just the thing one wants to avoid when using a timetable. Thus, I personally think that at least for me the ability to initialize a timetable with quite realistic values in the absence of surprising events like traffic jam would be the more relevant feature here. Of course, if you don´t want to do the detail work necessary for getting a precise picture of where trains are supposed to meet etc., and use timetables just for defining some distances between trains sharing the same orderlist, then such a feature makes sense.

Regarding buffer times, one might think define general settings in the advanced settings (e.g. always add x % to the calculated travel times, always stay for x days in a station), and use copies of those values while initializing a concrete timetables. I don´t think that you need these values dynamically stored for each order and each vehicle, because the vehicle needs a precise order "depart at X" anyway (instead of "depart at some time between X and Y").

In general, I see this as a possible add-on feature.

Quote:
Quote:
Specifically, based on my understanding of an autoseparation feature, to what degree would the underlying problem be solved by a simple solution for manually defining offsets between vehicles as stated above?

as far as i understand you, that would be version 1 above. the advantage of that is that it is algorithmically very simple, the disadvantage is that it cannot react on vehicles being late.


Well, except that you have to determine the roundtrip manually as long as no one implements that, and define offsets one time thereafter, handling version 1 should be quite simple. Handling version 3 should also be quite simple, here you need the (round-)trip times of a vehicle, and then think about where it should meet other vehicles. For such cases, my goal is supporting a train graph.

Version 2 is some kind of simple AI that does something with your timetable information. For me this is more or less out of scope because I know that all these topics we discuss here are more than enough work, but in principle, it is nothing I would block with my concept.


Top
 Profile  
 
PostPosted: Sun Apr 29, 2012 7:04 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Just a short question:

I am just redesigning the timetable window, remove some GUI elements, add others. Thus, I alter the set of GUI constants defined in src/widgets/timetable_widget.h

I got errors about undefined symbols in src/script/api/script_window.hpp. I was a bit surprised about the existence of that file, but ok, as a first step I removed all definitions for symbols I removed.

Next, it complains about the same set of symbols in src/script/api/game/game_window.hpp.sq . According to the comment that file is auto-generated. In the first place, I wonder wether I have to do something for triggering auto-generation of that file?

And, in general, what is the right sequence of tasks one has to do regarding src/script/api/, when changing symbols in src/widgets/ ? Am I right that script_window.hpp is supposed to contain a definition for any such symbol? If yes, would auto-generating that file be an option?


Top
 Profile  
 
PostPosted: Sun Apr 29, 2012 7:40 pm 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 4576
you need to run src/script/api/squirrel_export.sh

_________________
You might not exactly be interested in Ferion, but if you are, have fun :)


Top
 Profile  
 
PostPosted: Fri May 11, 2012 7:22 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
I am thinking about what to do with implicit orders, i.e. how to include them into my concept (or maybe exclude...). I know that they appear out of thin air in certain situations, especially if some vehicle missed its usual path and passes a station it is not supposed to pass. However, I never felt that I need them (I usually tell my vehicles in a quite detailed way what they should do), nor did I actually understand what purpose they serve, i.e. what problem of gameplay they do address.

Thus question: Can you describe, what purpose implicit orders serve, in what situations they are useful, why you need them?

Given your answers, I can hopefully avoid missing an important point about them :mrgreen:


Top
 Profile  
 
PostPosted: Fri May 11, 2012 8:16 pm 
Offline
OpenTTD Developer
OpenTTD Developer

Joined: Sun Sep 09, 2007 5:03 am
Posts: 2456
Location: home
Afaik, they serve two purposes, in different versions of OpenTTD.

In trunk, they add vehicles to stations that they visit more precisely. That means when you click 'vehicles visiting this station' the list is now more complete as it also contains vehicles visiting implicitly.

In cargo-d*st/yacd, the information is used to decide when cargo can be loaded onto a train.


Top
 Profile  
 
PostPosted: Sat May 12, 2012 7:46 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Thanks, this makes it clearer. So, to summarize, the main sense of implicit orders is making certain other features work better.

Another, rather technical question:

I noticed that SCC_DATE_* do not test for the INVALID_DATE. But I can have INVALID_DATEs embedded in a longer string. So I thought I write a small patch. The result was code as follows, in strings.cpp:

Code:
         case SCC_DATE_LONG: { // {DATE_LONG}
            Date date = args->GetInt32(SCC_DATE_LONG);
            if (date == INVALID_DATE) {
               buff = GetString(buff, STR_INVALID_DATE, last);
// Strange line         args->offset++;
            } else {
               buff = FormatYmdString(buff, date, last, next_substr_case_index);
            }
            next_substr_case_index = 0;
            break;
         }


The if/else distinction above is from me. My problem is: In the if-case, where I use a parameterless string, the offset is not increased although I use GetInt32 already before the if. And for me, the GetInt64 function (where GetInt32 delegates to) looks like increasing the offset. However, it does not happen, i.e. if I place an output statement at the begin and the end of the above block, without the line marked "Strange line" the offset isn´t increased.

But I doubt that increasing the offset manually is the intended solution (or is it actually?)

Also, I so far do not really understand the sense of the parameter of GetInt32 (however, at first glance the code doesn´t look like manipulating the offset in reaction to the parameter).

So question: What is happening here, and what is the correct way to code this? (I just spend a debugging hour on this :-( )


Top
 Profile  
 
PostPosted: Sun Jul 22, 2012 11:16 am 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
I am not yet ready for a release, but I thought I could make a screenshot what I have so far for you ;-)

What I have (and you can see on the screenshot) is:

A route management GUI, which offers assembling a sequence of stations/depots/waypoints/free-chosen map tiles to a route.

The player then can choose routes as vias in the order window. I added an optional mode where Go To uses the network of routes the player entered, and suggests destinations that are reachable from the previous destination via some route (the window at the right).

I also merged the order window into the timetable window, in the upper line of an order you can administrate all things (non-stop, full load, etc.) known from the orders window, the lower line is for the timetable related things.

Timetables have the concept I describe above in this thread, i.e. departures and arrivals are absolute, a timetable has a start date and a length. Vehicles have offsets against timetables, this way one can easily specify the data of multiple vehicles using a common timetable. When all offsets of shared vehicles are greater than the timetable length, the whole timetable will be moved into the future to keep offsets small.

Using absolute timetable data, timetables should become much more robust (e.g. changing some arrival in between does not affect the others) and understandable (one doesn´t have to sum up relative times oneself). For easily entering timetable data, I added a special date entering window (not shown) with basically the layout "-10 -5 -1 5.5.1922 +1 +5 +10", which automatically goes to the next arrival/departure once the player entered one.

Missing are tests, the station and route timetable GUIs, as a ultimative goal the traingraph I can conceptionally offer using the routes the player entered and connected with the orders.

Attachment:
Bronfingburg Transport, 8th Jun 1922.png [256.69 KiB]
Downloaded 4 times


Top
 Profile  
 
PostPosted: Mon Jul 23, 2012 8:19 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Question: The following abort - what situation does it describe, which .lng-file does the message refer to and on what would you have a look at? Is there something I would have to generate, similar to the squirrel_export?

Background: The dialog it tries to open is implemented by me, I am almost sure that the click at hand already worked some months ago (had a major break with the work at that patch), its description is below the error message.

Code:
Error: String 0xB698 is invalid. You are probably using an old version of the .lng file.
                                                                                                                                                                                                                                             

Program received signal SIGABRT, Aborted.
0xb7fe2424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7fe2424 in __kernel_vsyscall ()
#1  0xb7b71911 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64
#2  0xb7b74d42 in *__GI_abort () at abort.c:92
#3  0x0831e9fe in error (s=0x8533ef8 "String 0x%X is invalid. You are probably using an old version of the .lng file.\n") at /home/wol/openttd/_trunk_tip/src/openttd.cpp:120
#4  0x08415c3c in GetStringWithArgs (buffr=0xbfffa6c0 ">>", string=46744, args=0xbfffa350, last=0xbfffaebf "\250\230\233\261\250\260R\262\250\230\233\261\250G6H\bH\257\377\277?\210", case_index=0, game_script=false)
    at /home/wol/openttd/_trunk_tip/src/strings.cpp:216
#5  0x084102a1 in FormatString (buff=0xbfffa6c0 ">>", str_arg=<optimized out>, args=0x86b4840, last=0xbfffaebf "\250\230\233\261\250\260R\262\250\230\233\261\250G6H\bH\257\377\277?\210", case_index=0, game_script=false, dry_run=true)
    at /home/wol/openttd/_trunk_tip/src/strings.cpp:1100
#6  0x08413957 in FormatString (buff=0xbfffa6c0 ">>", str_arg=0xb703c449 "", args=0x86b4840, last=0xbfffaebf "\250\230\233\261\250\260R\262\250\230\233\261\250G6H\bH\257\377\277?\210", case_index=0, game_script=false,
    dry_run=false) at /home/wol/openttd/_trunk_tip/src/strings.cpp:845
#7  0x08415770 in GetStringWithArgs (buffr=0xbfffa6c0 ">>", string=34879, args=0x86b4840, last=0xbfffaebf "\250\230\233\261\250\260R\262\250\230\233\261\250G6H\bH\257\377\277?\210", case_index=0, game_script=false)
    at /home/wol/openttd/_trunk_tip/src/strings.cpp:219
#8  0x08415cff in GetString (buffr=0xbfffa6c0 ">>", string=34879, last=0xbfffaebf "\250\230\233\261\250\260R\262\250\230\233\261\250G6H\bH\257\377\277?\210") at /home/wol/openttd/_trunk_tip/src/strings.cpp:226
#9  0x082721de in GetStringBoundingBox (strid=34879) at /home/wol/openttd/_trunk_tip/src/gfx.cpp:1057
#10 0x08483647 in NWidgetLeaf::SetupSmallestSize (this=0xa8b252b0, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:2281
#11 0x08483f70 in NWidgetHorizontal::SetupSmallestSize (this=0xa8b25080, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:1098
#12 0x08483d10 in NWidgetVertical::SetupSmallestSize (this=0xa8b25030, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:1260
#13 0x08483d10 in NWidgetVertical::SetupSmallestSize (this=0xa8b564c8, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:1260
#14 0x08482f78 in NWidgetBackground::SetupSmallestSize (this=0xa8b24fc8, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:1707
#15 0x08483d10 in NWidgetVertical::SetupSmallestSize (this=0xa8b19d58, w=0xa8b19b98, init_array=true) at /home/wol/openttd/_trunk_tip/src/widget.cpp:1260
#16 0x0848d225 in Window::InitializeData (this=0xa8b19b98, desc=0x8605c80, window_number=0) at /home/wol/openttd/_trunk_tip/src/window.cpp:1162
#17 0x0848dd5b in Window::FinishInitNested (this=0xa8b19b98, desc=0x8605c80, window_number=0) at /home/wol/openttd/_trunk_tip/src/window.cpp:1506
#18 0x082368ae in SetDurationWindow (callback=0x8422000 <SetLengthCallback(Window const*, Duration)>, caption=3162, initial_duration=..., parent=0xa8b08c78, window_number=0, desc=0x8605c80, this=0xa8b19b98)
    at /home/wol/openttd/_trunk_tip/src/duration_gui.cpp:122
#19 ShowSetDurationWindow (parent=0xa8b08c78, window_number=0, initial_duration=..., caption=3162, callback=0x8422000 <SetLengthCallback(Window const*, Duration)>) at /home/wol/openttd/_trunk_tip/src/duration_gui.cpp:324
#20 0x0842b1b3 in TimetableWindow::OnClick (this=0xa8b08c78, pt=..., widget=26, click_count=1) at /home/wol/openttd/_trunk_tip/src/timetable_gui.cpp:1221
#21 0x0848fb3d in DispatchLeftClickEvent (click_count=1, y=123, x=616, w=0xa8b08c78) at /home/wol/openttd/_trunk_tip/src/window.cpp:496
#22 MouseLoop (mousewheel=<optimized out>, click=<optimized out>) at /home/wol/openttd/_trunk_tip/src/window.cpp:2455
#23 HandleMouseEvents () at /home/wol/openttd/_trunk_tip/src/window.cpp:2544
#24 0x08471b55 in PollEvent () at /home/wol/openttd/_trunk_tip/src/video/sdl_v.cpp:457
#25 VideoDriver_SDL::MainLoop (this=0x8701108) at /home/wol/openttd/_trunk_tip/src/video/sdl_v.cpp:571
#26 0x0831ffd1 in ttd_main (argc=1, argv=0xbffff564) at /home/wol/openttd/_trunk_tip/src/openttd.cpp:848
#27 0x0815d848 in main (argc=1, argv=0xbffff564) at /home/wol/openttd/_trunk_tip/src/os/unix/unix.cpp:275
(gdb)


Description of the dialog:
Code:
/** Widgets for the date setting window. */
static const NWidgetPart _nested_set_duration_widgets[] = {
   NWidget(NWID_HORIZONTAL),
      NWidget(WWT_CLOSEBOX, COLOUR_BROWN),
      NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SDU_CAPTION), SetDataTip(STR_DURATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
   EndContainer(),
   NWidget(WWT_PANEL, COLOUR_BROWN),
      NWidget(NWID_VERTICAL), SetPIP(6, 6, 6),
         NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(6, 6, 6),
            NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SDU_FAST_SMALLER_BUTTON), SetMinimalSize(20, 12), SetDataTip(STR_DURATION_FAST_SMALLER_BUTTON_CAPTION, STR_DURATION_FAST_SMALLER_BUTTON_TOOLTIP),
            NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SDU_SMALLER_BUTTON), SetMinimalSize(20, 12), SetDataTip(STR_DURATION_SMALLER_BUTTON_CAPTION, STR_DURATION_SMALLER_BUTTON_TOOLTIP),
            NWidget(WWT_EDITBOX, COLOUR_GREY, WID_SDU_LENGTH_EDITBOX), SetMinimalSize(80, 12), SetResize(1, 0), SetFill(1, 0), SetPadding(2, 2, 2, 2),
               SetDataTip(STR_DURATION_ENTER_LENGTH_OSKTITLE, STR_DURATION_ENTER_LENGTH_TOOLTIP),
            NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SDU_BIGGER_BUTTON), SetMinimalSize(20, 12), SetDataTip(STR_DURATION_BIGGER_BUTTON_CAPTION, STR_DURATION_BIGGER_BUTTON_TOOLTIP),
            NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SDU_FAST_BIGGER_BUTTON), SetMinimalSize(20, 12), SetDataTip(STR_DURATION_FAST_BIGGER_BUTTON_CAPTION, STR_DURATION_FAST_BIGGER_BUTTON_TOOLTIP),
            NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_SDU_UNIT_DROPDOWN), SetFill(1, 0), SetDataTip(STR_JUST_STRING, STR_DURATION_UNIT_DROPDOWN_TOOLTIP),
         EndContainer(),
         NWidget(NWID_HORIZONTAL),
            NWidget(NWID_SPACER), SetFill(1, 0),
            NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_SDU_CHOOSE_BUTTON), SetMinimalSize(80, 12), SetDataTip(STR_DURATION_CHOOSE_DURATION_BUTTON_CAPTION, STR_DURATION_CHOOSE_DURATION_BUTTON_TOOLTIP),
            NWidget(NWID_SPACER), SetFill(1, 0),
         EndContainer(),
      EndContainer(),
   EndContainer()
};


Top
 Profile  
 
PostPosted: Mon Jul 23, 2012 8:57 pm 
Offline
OpenTTD Developer
OpenTTD Developer

Joined: Thu Feb 09, 2006 7:15 pm
Posts: 3704
Looks like a SetDParam which sets the wrong value, which is then somewhere in some string used as if it were a {STRING}. That string number does not exist and it aborts.

The equivalent of squirrel_export for strings is called strgen, but that is automatically called during builds.


Top
 Profile  
 
PostPosted: Tue Jul 24, 2012 1:04 am 
Offline
Tycoon
Tycoon

Joined: Wed Jan 17, 2007 12:14 am
Posts: 4576
the string resolving/display functions are in dire need of better sanitising the input. especially since strings are providable by newgrf, and their parameters might not match the ones that are expected by the game. (e.g. in nml write "{STRING}" in a vehicle name, and openttd crashes on displaying the vehicle list, because no string was previously pushed on the stack. see http://bugs.openttd.org/task/5043)

_________________
You might not exactly be interested in Ferion, but if you are, have fun :)


Top
 Profile  
 
PostPosted: Mon Jul 30, 2012 11:45 pm 
Offline
Engineer
Engineer

Joined: Wed Mar 18, 2009 1:58 pm
Posts: 75
looks great - a routes - i see that routes can be changed eg R1 then R2 then back - its useful for my game


Top
 Profile  
 
PostPosted: Sun Sep 02, 2012 2:44 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
A programming question:

Consider the attached source file. It contains / will contain the source of a Timetable window. As there are small parts of code different, depending on the question wether we talk about stations, depots, etc., I thought I put all the painting, calculation etc. code into the upper class LocationTimetableWindow, and add specialized classes NodeTimetableWindow, StationTimetableWindow, etc. which contain the special code, which basically consists of one virtual function of about 10 lines of code, and possible some string getters lateron.

So far, conceptionally I see no problem.

However, I simply cannot make it call StationTimetableWindow::GetAffectedOrders from LocationTimetableWindow::CalculateScheduledVehicleLocations, it always takes LocationTimetableWindow::GetAffectedOrders (the latter was originally a pure virtual function, with the corresponding error at run time...). And I don´t understand why it apparently is not being overridden.

Do you see any obvious mistake in my code? Is there anything special about the Window class that forbids overriding a subclass of Window? Any special magic, like that the new[] and delete operators are disabled?

The workaround would obviously be throwing away those subclasses and simply working with an enum, but I regard subclasses as the nicer programming style for the problem at hand. If just I would be able to make them work...


Also: Given that a timetable window is intended to be updated on a regular manner: What is the right way to trigger that, in some regular intervals? E.g. once a day or so...


Attachments:
nodetimetable_gui.cpp [15.83 KiB]
Downloaded 23 times
Top
 Profile  
 
PostPosted: Sun Sep 02, 2012 3:20 pm 
Offline
OpenTTD Developer
OpenTTD Developer

Joined: Sun Sep 09, 2007 5:03 am
Posts: 2456
Location: home
ic111 wrote:
So far, conceptionally I see no problem.
Seems fine conceptually.

ic111 wrote:
However, I simply cannot make it call StationTimetableWindow::GetAffectedOrders from LocationTimetableWindow::CalculateScheduledVehicleLocations, it always takes LocationTimetableWindow::GetAffectedOrders (the latter was originally a pure virtual function, with the corresponding error at run time...). And I don´t understand why it apparently is not being overridden.
So what did it say with a pure virtual function?
That should give you a clue what is wrong, imho.

ic111 wrote:
Do you see any obvious mistake in my code? Is there anything special about the Window class that forbids overriding a subclass of Window? Any special magic, like that the new[] and delete operators are disabled?
There is some zero-ing of memory magic afaik, but that's it. I am not even sure you can prevent sub-classing in C++ in the first place, I would not know how to do that.

Quote:
Also: Given that a timetable window is intended to be updated on a regular manner: What is the right way to trigger that, in some regular intervals? E.g. once a day or so...
Looking at some other windows should show you. Basically you can do an update based on time (there is a method that gets called regularly, add a counter, and a SetDirty() or so). Alternatively, a window can be informed about relevant events from the game engine.


Top
 Profile  
 
PostPosted: Sun Sep 02, 2012 5:07 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Ok, thank you, I solved it: It was an instance of "do not try to call a virtual function from a constructor".

Quote:
ic111 wrote:
However, I simply cannot make it call StationTimetableWindow::GetAffectedOrders from LocationTimetableWindow::CalculateScheduledVehicleLocations, it always takes LocationTimetableWindow::GetAffectedOrders (the latter was originally a pure virtual function, with the corresponding error at run time...). And I don´t understand why it apparently is not being overridden.
So what did it say with a pure virtual function?
That should give you a clue what is wrong, imho.


Well, the original error here unfortunately actually was just "pure virtual function called" at the beginning of OpenTTDs usual stacktrace when it crashes.

When I added a test call directly in the constructor (the other one was called indirectly via InvalidateData which I added more for test purposes), the linker complained.

Quote:
ic111 wrote:
Do you see any obvious mistake in my code? Is there anything special about the Window class that forbids overriding a subclass of Window? Any special magic, like that the new[] and delete operators are disabled?
There is some zero-ing of memory magic afaik, but that's it. I am not even sure you can prevent sub-classing in C++ in the first place, I would not know how to do that.


I don´t know any either, but.... there are *many* things you can do in C++, so I would not absolutely deny that you might be able to do things in a way that as a result subclassing is broken...

Quote:
Quote:
Also: Given that a timetable window is intended to be updated on a regular manner: What is the right way to trigger that, in some regular intervals? E.g. once a day or so...
Looking at some other windows should show you. Basically you can do an update based on time (there is a method that gets called regularly, add a counter, and a SetDirty() or so). Alternatively, a window can be informed about relevant events from the game engine.



Ah, ok, thank you either, I overlooked that it is that easy :-)
(I have expected some magic in some central game loop).


Top
 Profile  
 
PostPosted: Wed Dec 05, 2012 6:42 pm 
Offline
Engineer
Engineer
User avatar

Joined: Fri Jul 09, 2010 6:07 pm
Posts: 15
Location: Minsk, Belarus
In this topic silence means sadness. :?

_________________
Belarusian translation for OpenTTD
Epochal xUSSR Set


Top
 Profile  
 
PostPosted: Wed Dec 05, 2012 8:28 pm 
Offline
Transport Coordinator
Transport Coordinator

Joined: Tue Jul 17, 2007 5:56 pm
Posts: 270
Well, basically most of the work is done, but real life currently doesn´t leave much room for the remaining tasks of bugfixing and improving GUI handling and implementing some last features. Which need to be done before I can publish a version that can be called playable...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 38 posts ]  Go to page Previous  1, 2

All times are UTC


Who is online

Users browsing this forum: Google Adsense [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  

Powered by phpBB © 2000-2013 phpBB Group

Copyright © Owen Rudge/The Transport Tycoon Forums 2001-2013.
Hosted by Zernebok Hosting.