You can also look at the dispatch controller code, that handles the waiting, selection, etc (it's in controller.cpp).
controller.cpp seems to be the main part in question here. I did take a quick look at it earlier today, and it looks like it still works much the same way I remember it working back in "the old days"... or at least how it did once it was implemented in the first place. I vaguely remember the dispatching logic briefly just being "call the first elevator" back when I first played Skyscraper.
I'm not that great at reading C++ (or C), so I did a bit of a test as well, using the "Express to 134 to 136" elevators (33 and 34) in the back of the Triton Center. I did the following:
- Placed car 33 on floor 136
- Placed car 34 at the lobby
- Placed the camera on floor 136
- Waited for all elevators to be idle, in normal operation, and with the doors closed
- Placed a down hall call on floor 136 (which was answered immediately by car 33), then a car call in car 33 for floor 135, then waited for the doors to close
- Immediately after the doors closed, placed another down hall call on floor 136
I observed what the two elevators did after I placed the second hall call, and it appears that car 34 was initially selected and began moving upwards. Once car 33 became idle, the call was moved ("Dispatch Controller 12: Switching to closer elevator 33"), car 33 answered the call, and car 34 stopped in the express zone(!) at floor 39.
I would expect a typical ETA-based dispatcher to have initially selected car 33 instead, as the time needed to finish serving the car call on floor 135 and then return to floor 136 is much less than the time needed to travel from the lobby all the way to floor 136.
As another test, I did this on the same two elevators:
- Started with the camera on floor 136, car 33 on floor 135, and car 34 on floor 134, both idle, in normal operation, and with the doors closed
- Changed the UpSpeed value for car 33 from the default of 30 to 0.25. The UpSpeed value for car 34 was left at 30.
- Placed a down hall call on floor 136
In this case, car 33 responded to the call, even though the time that car 34 would take to travel 2 floors is significantly less than the time car 33 took to travel one floor at the reduced speed. A typical ETA-based dispatcher would have assigned the call to car 34 as it would have been able to arrive sooner.
And for a third and final (for now) test, I went for the first elevators I ever tried in the Triton Center (cars 25 and 26), and:
- Started with the camera on floor LL1 and cars 25 and 26 both on floor P5, both idle, in normal operation, and with doors closed
- Placed a car call for floor L in car 26
- Immediately (before car 26 reached floor P4) placed an up hall call on floor LL1
The behavior in this case varied depending on which button I pressed in the elevator editor, as I'm not sure which button is for placing a normal car call. If I entered the car call by pressing "Enqueue Up", then car 26 continued past floor LL1 and stopped at floor L, while car 25 answered the hall call on floor LL1. If I instead pressed "call", then cars 25 and 26 both stopped at floor LL1 (car 25 indicated up, while car 26 did not indicate a direction when it opened). Car 26 did not go anywhere after the doors closed and seemed to just drop the call for floor L entirely.
In this case, I would have expected a typical dispatcher to select car 26, as it would have been able to stop in time to answer the call on floor LL1, and would be able to get there sooner compared to the car that had not yet even started moving. In this specific case however, I can also see how some dispatchers may be tuned to prioritize more non-stop rides over fastest arrival, and in those cases at least one of Skyscraper's behaviors would be reasonable, but this is not a typical thing for dispatchers to optimize for.
If you'd like to take a look at my dispatching code, it's in
dispatcherfw.lua. I took a similar approach to how Skyscraper currently works in that the code handling the dispatching is separate from the controllers for each car and also from the call buttons (which are just an input into it), except in this case it's actually a physical object in the world. It can be seen in a few of the screenshots on the ContentDB page, it's the white cabinet with the "D" label on the corner (the ones without the label are controllers).
As of the commit I linked (which, right now, is the latest), the important part is on lines 616-763, where the ETAs for each car are compared and used to select which car to send the call to. This part runs about once per second when there are calls present (it does stop under some conditions, the details of which aren't important right now). The calculateeta() function that it calls in a few places is the one doing a lot of the heavy lifting - it's defined on line 276 of the same file.
Specifically, calculateeta() obtains a list of what the elevator would hypothetically do if it was to be assigned the call, then works through each step and adds up how long it would be expected to take, before finally returning a total time. To do that, it uses estimatetraveltime() (line 233), which takes two floors and a car number and estimates how long it would take to travel between the two (including acceleration/deceleration). The list of what the elevator would do comes from buildstopsequence() (line 242), which does a bit of work to figure out where the car is starting from and in which direction, then calls predictnextstop() (line 187) repeatedly to determine where the elevator will go next after it answers each call. The logic in predictnextstop() is nearly the same as the logic in the controller itself that finds the call it will serve next after the doors close.
For example, if it wants an ETA for car 1 for an up hall call on the 3rd floor and the car already has several calls, buildstopsequence() might come up with something like this:
- 5th floor car call
- 7th floor up call
- 8th floor car call
- 10th floor down call
- 8th floor down call
- 3rd floor down call
- 1st floor up call
- 3rd floor up call (the call being searched for, so it stops making the list here)
calculateeta() then calls estimatetraveltime() for each pair (5 to 7, 7 to 8, 8 to 10, 10 to 8, 8 to 3, 3 to 1, and 1 to 3), adds these together along with some extra to account for the doors opening and closing, then returns a number. If this number is lower than the ones for all other cars that could serve this call (or no other elevators can), then it goes to this one.