THE PROGRAM

The Orient Express program consists of a main program, initialization section, end-game section, nine major subroutines, and nine short subroutines.

In the initialization section (Lines 180260), variables are dimensioned, and text and numeric data are read into variables in four separate subroutines. Before the data are loaded, the program enters a loop which increments the value of the seed for the random-number generator, RN. This loop is terminated when any key is pressed (Line 140). If the value of RN is above the acceptable maximum (32767), 65535 is subtracted until the value of RN is within the range acceptable to the Randomize statement.

The last function performed in the initialization section is the shuffling of 24 integers. These are used later to determine the order in which the conversations with various passengers occur. Shuffling is an important function in many games, particularly those involving cards. In mathematical terms, shuffling is defined as a random permutation, that is, generating the numbers from 1 to N in a random order without repetition. Consider this routine, commonly found in beginning programming texts, for shuffling 10 integers into M(1) to M(10):

10 FOR I = 1 TO 10
20    K = INT(1 + 10 * RND(1))
30    FOR J = 1 TO I
40       IF M(J) = K THEN 20
50    NEXT J
60    M(I) = K
70 NEXT I

A random number between 1 and 10 is generated in Line 20. This is then checked against all of the elements of M to see if it has already been used; if not, the current element of M, that is, M(I), is set equal to K. If it has been used, a new value of K is generated in Line 20. The routine is short, easy to understand, and horribly inefficient (the execution speed is proportional to the square of the numbers to be shuffled).

Consider this approach:

10 FOR I = 1 TO 10
20    M(I) = I
30 NEXT I
40 FOR I = 1 TO 9
50    K = I + INT((11 - I) * RND(1))
60    T = M(I)
70    M(K) = M(I)
80    M(I) = T
90 NEXT I

The program is two lines longer because of the necessity to load the array M(1) to M(10) with the integers 1 to 10 in Lines 10 to 30. However, the execution speed is much faster than the previous algorithm, as it is proportional to two times the numbers to be shuffled. The heart of the algorithm is found at Line 50. The first time through the loop, this function selects a random integer between 1 and 10; the second time through, between 2 and 10; the third time, between 3 and 10; and so on. The elements chosen are then exchanged with the values currently in those elements. If we think of the elements as cards, we could think of picking up one random card at a time from the deck, placing it on a pile, and then picking the next card. The final pile will thus be thoroughly shuffled. In the program, this subroutine is found at Lines 27602790.

The main program prints the scenario and then iterates through the 24 segments of the train journey. For each segment, the date is printed followed by the location and the arrival time. The scheduled arrival time is found in the data variable TA(n). The actual arrival time is determined by a random function at Line 310 and can be from 8 minutes early to 18 minutes late.

In some cases this function will produce a time like 271 or 1460. This problem is cured in the subroutine that prints out the time (Lines 30603090). The last two digits of the time are examined in Line 3070, and if they are found to exceed 59, one hour is added and 60 minutes are subtracted; this is accomplished by simply adding the integer 40 to the numeric value of the time. This subroutine then divides the time into strings representing hours and minutes and prints it in the correct format such as 3:11 or 15:00. The integer 10000 is added to the numeric value of the time so that the leading zeroes will be printed.

If an intermediate station is reached at night during sleeping hours, arrival and departure times are simply noted, and the program proceeds. If the stop is during waking hours, you are given a chance to get off the train and stretch your legs.

On the first segment of the trip out of London, you ask passengers to keep alert for information of value (Lines 520560). Each segment of the trip has a series of data values which indicate the number of conversations with passengers that can take place (CN(n)), the meal to be served (ME(n)), and the potential hazards (HZ(n)). After the subroutines for each of these items are called in Lines 580610, the program goes on to the next trip segment.

The breakfast and dinner subroutines (Lines 640700 and 770840) are similar. Each one asks if you are ready to go to the restaurant car for the meal and enters an endless loop until you press a key. The menu is then presented. Menu items are selected at random and printed on the screen. Items are centered by the LOCATE statement in Lines 690 and 820, which takes the length of the item, 80 (the width of the screen), divides by two, and moves the cursor to that location to start printing. At the conclusion of the meal, a loop, which waits until any key is pressed to clear the menu from the screen, is entered in the subroutine at Lines 29502970.

The subroutine to present the conversations you have with the passengers iterates through the conversations, if any, on the current trip segment. If a conversation is to be held, the number of that conversation, CS(CM), is selected from the previously shuffled list. In Line 910 the length of the string containing the conversation is checked. If it is fewer than 80 characters long, it is displayed on one screen line. If it is longer than 80 characters, the routine in Lines 920 and 930 starts iterating from the 79th character backward looking for a space. When one is found, the left side of the string up to that point (the first part of the conversation) is printed and, on the next line, the right side of the string from the space on is printed (the last part of the conversation).

Two subroutines for hazardssnowdrifts, bandits, and derailmentsare nearly identical except for the dialog. There is a 65% chance of snow on three of the trip segments (Line 980). If it is snowing heavily, there is a 1% chance of getting stuck in a snowdrift.

If this happens, the trip is delayed for two days until the snow is cleared from the tracks. This routine could be made much more elaborate to simulate the time the train was stuck in a snowdrift for six days in 1929. However, that was an isolated incident, and every other time the train was stuck it resulted only in a delay and very little discomfort to the passengers.

On two trip segments in Bulgaria and Turkey, there is a 4% chance that bandits will board the train and rob the passengers. On the actual Orient Express robberies were an infrequent occurrence and, except for two instances in May and October 1891 when people on the train were kidnapped and held for ransom, bandits rarely hurt anyone, being content to steal money and jewelry.

On all trip segments there is a 2% chance of a derailment. In the event that this occurs, the locomotive, tender, and first mail coach will leave the track, and you will be stranded somewhere for a day until the track is repaired and a replacement locomotive obtained.

The probability of any of the above three hazards occurring in the program is much higher than it was in actuality. However, if the probabilities were reduced to the few thousandths of one percent that existed in reality, you might have to play the game tens of thousands of times to experience even a single misadventure.

The final major subroutine (Lines 14901690) checks the identities of the killer and defector that you input in the previous subroutine (Lines 13401470) with the actual identity. There are seven possible situations which can lead to any of five different eventual outcomes (see chart).
_________IF YOU DO THIS_________    _______________ THEN THIS HAPPENS _______________
Killer ID'd as  Defector ID'd as    Defector killed  You killed  Defector wrongly arrested
   Killer          Defector              No              No          No
   Killer          Nobody                Yes             No          No
   Nobody          Defector              No              Yes         No
   Nobody          Nobody                Yes             Yes         No
   Nobody          Killer                No              Yes         Yes
   Defector        Nobody                Yes             Yes         No
   Defector        Killer                No              Yes         Yes

The correct dialog for the three possible nasty events (defector killed, you killed, and defector wrongly arrested) can be selected with just three IFTHEN statements (Lines 1500, 1600, and 1630). If you get both identities correct, the indicator A5 is set equal to 1 so that you receive a congratulatory message when you arrive in Constantinople.

The short subroutines (Lines 27603140) are all self-explanatory; they simply produce pauses in program execution, make train noises, check for yes/no answers, and the like. The end-game segment (Lines 31893330) presents an end-game message, displays a message of congratulations if you got both indentities correct, and asks if you want to ride again.

PROGRAM VARIABLES
A Answer of user (0 = yes, 1 = no)
A$ Answer to string-input query, user input
A1, A2 Answer to identity of defector and killer, user input
A3, A4 Actual identity of defector and killer
A5 Indicates if user identifications were correct
C$(n) Conversations of passengers, n = 1 - 24
CM Conversation number, index of CS
CN(n) Number of conversations per trip segment, n = 1 - 24
CP(n) Conversation indicator (0 = passenger, 1 = waiter, 2 = cook), n = 1 - 24
CS(n) Conversation number, n = 1 - 24
DA(n) Day of trip by trip segment, n = 1 - 24
HW Hazard, derailment indicator
HX Hazard, bandit-attack indicator
HY Hazard delay in days
HZ(n) Hazards on each trip segment, n = 1 - 24
I Index indicator
J Trip-segment indicator
K, KA Index indicators
LA$(n) City, n = 1 - 24
LB$(n) Country, n = 1 - 24
MB$(n) Meal, breakfast, name of menu item, n = 1 - 13
MD$(n) Meal, dinner, name of menu item, n = 1 - 25
ME(n) Meal indicator by trip segment, n = 1 - 24
N$(n) Names of passengers, n = 1 - 25
RN Random seed for random-number generator
T Time, temporary for printing
T$ Time, string variable, temporary for printing
TA(n) Time of arrival, scheduled, by trip segment, n = 1 - 24
TB Time of arrival, actual
TD(n) Time of departure by trip segment, n = 1 - 24
TN Time, minutes early or late
X Temporary variable
X$ Temporary string variable

