Decoded: Sopwith (1984) by David L. Clark
Source file: SWAUTO.C
Beginner friendly, line-by-line code walkthrough by MaiZure

SWAUTO.C defines functions for the AI planes that fight the player

Original code:
http://davidlclark.com/page/sopwith-source-code

Original code with line numbers
http://www.maizure.org/projects/decoded-sopwith/SWAUTO_linenum.txt



1     COMMENT
2     COMMENT
3     BLANK
4     COMMENT
5     COMMENT
6     COMMENT
7     COMMENT
8     COMMENT
9     COMMENT
10    COMMENT
11    COMMENT
12    COMMENT
13    COMMENT
14    BLANK
15    COMMENT
16    BLANK
17    COMMENT
18    COMMENT
19    COMMENT
20    COMMENT
21    COMMENT
22    COMMENT
23    COMMENT
24    COMMENT
25    COMMENT
26    COMMENT
27    COMMENT
28    COMMENT
29    COMMENT
30    Includes the main game header (sw.h)
31    BLANK
32    Import the sine table defined in SWMAIN.C
33    Import the current ground array
34    Import the base ground array
35    Import the object list
36    Import the plane object pointers
37    Import the AI plane tracking array
38    Import the target array
39    Import the left AI territory markers
40    Import the right AI territory markers
41    Import the object pointers for the lists
42    Import the display functions
43    Import the key delay
44    Import the current play mode
45    Import the victory flag
46    Import the victory countdown timer
47    Import the game speed
48    Import the computer plane flag
49    Import the player plane flag
50    Import the current object index
51    Import the performance counters
52    BLANK
53    BLANK
54    Declare a local flag for course corrections
55    Declare a local flag for returning to base
56    Declare a local object to hold a computer instance
57    Declare a local variable for course adjustment
58    BLANK
59    BLANK
60    BLANK
61    BLANK

MAIN AI CONTROL
62    Declare and define swauto with one argument
63    First argument is the pointer to the input object (AI plane)
64    BLOCK START - swauto, perform AI actions
65    Declare a local variable  
66    BLANK
67    Plane under control is not returning to base
68    BLANK
69    If there is a valid target within range...
70    Attack the target
71    Otherwise...
72    If plane isn't at home..
73    It should cruise around
74    BLANK
75    Assume there is no target until the next AI loop
76    BLOCK END - swauto
77    BLANK
78    BLANK
79    BLANK
80    BLANK
81    BLANK

AI ATTACK
82    Declare attack with two arguments
83    Both arguments are pointers, the attacker and the target
84    BLOCK START - attack, engage the player
85    Declare a local object pointer
86    BLANK
87    Course adjust ticks 16 units as a time, one per step through 240
88    Point to the input target
89    If the object is moving...
90    The shooter should aim...
91    A few pixels ahead of the targets x
92    And a few pixels ahead of the target y
93    Since we're attacking, the target is not a long way ahead
94    Otherwise the target isn't moving so..
95    Aim slightly above the target
96    BLOCK END - attack
97    BLANK
98    BLANK
99    BLANK
100   BLANK

AI CRUISING
101   Declare and define cruise with one argument
102   Argument is the pointer to the AI plane
103   BLOCK START - cruise, fly towards the target (player)
104   Declare a local variable for the crusing object's x coordinate
105   BLANK
106   Course adjust ticks 16 units as a time, one per step through 240
107   Capture the current object's x coordinate
108   If the plane is less than 1/3rd of the way across the map
109   It should cruise towards the 1/3 mark (go right)
110   But if it's beyond the 2/3rd point
111   It should cruise towards the 2/3rs point (go left)
112   Offset slightly based on course adjustment
113   It should fly around the top of the map
114   With no particular target
115   BLOCK END - cruise
116   BLANK
117   BLANK
118   BLANK
119   BLANK

AI RETURN TO BASE
120   Declares and defines gohome with one argument
121   Argument is the pointer to the AI plane
122   BLOCK START - gohome, return to base
123   Declare local pointers to the plane and potential targets
124   BLANK
125   If the plane is already at home..
126   Return, because we're already there
127   BLANK
128   Point to the current plane
129   BLANK
130   Course adjust ticks 16 units as a time, one per step through 240
131   BLOCK START - Arrive at base, if plane is within 16 x pixels of base..
132   and within 16 y pixels of base...
133   BLOCK START - Player RTB, If it's the player
134   Initialize player plane
135   Reset the display
136   BLOCK END - Player RTB
137   Other if it's the computer plane...
138   Initialize the plane at base
139   It must be a multiplayer plane...?
140   Initialize that plane at base
141   Return
142   BLOCK END - Arrive at base
143   Set return to base flag to true
144   Aim towards the 
145   BLOCK END - gohome
146   BLANK
147   BLANK
148   BLANK
149   BLANK
150   BLANK

AI SHOOTING
151   Declare and define shoot with one argument
152   Argument 1 is the target to shoot at
153   BLOCK START - shoot, attack the player
154   Declare local objects to mirror the shooter and target
155   Declare local variables for the position of both shooter and target
156   Declare local variables to hold speed and angle of either object
157   Delare local variable to last turning state
158   Declare a local variable to hold current turn/range and an iterator
159   BLANK
160   BLANK
161   Copy the global computer plane object to the local attacker object
162   Copy the target object to the local target object
163   Set our speed variable to the shooter speed plus the bullet speed
164   Update our shooter mirror object's movement vector with bullet movement
      characteristics to mimic a potential shot. Start with x input
165   Then y input
166   Update the shooter's start x position to halfway in to the graphic
167   Update the shooter's start y position to halfway in to the graphic
168   BLANK
169   Set our local angle variable to the target's angle
170   Set our local speed variable to the target's speed
171   Set our previous angle to a temporary variable
172   BLOCK START - Predict shot, simulate a bullet hitting the target
173   Update bullet position.
174   BLOCK START - Turning target, If the target is flying...
175   Or wounded...
176   And it is turning..
177   Then check it's orientation to determine it's turn direction
178   Adjust bullet angle for negative turn
179   Otherwise..
180   Adjust bullet angle for positive turn
181   New angle may have wrapped, take the mod
182   Update the target's x movement 
183   Update the target's y movement 
184   BLOCK END - Turning target
185   Update the target's position
186   Store the target's range 
187   If the range is beyond our interesting (too high or low)
188   We can't hit on the current vector so return fail
189   Otherwise If the bullet is beyond the target's start x
190   And before the target's end x
191   And beyond the target's start y
192   And before the target's end y
193   Return a positive value based on distance
194   BLANK
195   BLOCK END - Predict shot
196   We're here, so it missed. Return fail
197   BLOCK END - shoot
198   BLANK
199   BLANK
200   BLANK
201   BLANK

ABSOLUTE VALUE UTILITY
202   Declare and define abs with one argument
203   Argument 1 is an integer
204   BLOCK START - abs, absolute value utility
205   Return the absolute value of the input
206   BLOCK END - abs
207   BLANK
208   BLANK
209   BLANK
210   BLANK
211   BLANK
212   BLANK
213   BLANK

AI AIMING
214   Declare aim with five arguments
215   Arguments 1 and 4 are pointers to the attacker and target
216   Arguments 2 and 3 are the target's x and y coordinates
217   Argument 5 is a condition flag, usually false on init and true later
218   BLOCK START - aim, line up shot against player
219   Declare a local pointer the aiming and target objects
220   Declare local variables for range and indicies
221   Declare local variables for temporary positions
222   Declare local variables for speed and sngle
223   Declare a local array for turning states
224   Declare local arrays for all states of the game used to test aim actions
225   BLANK
226   Point to the input aiming object
227   BLANK
228   Initialize course correction to false
229   BLANK
230   If the aiming plane is stalled...
231   And it's not facing generally downward
232   Try to pull up
233   And speed up
234   Return from aiming (don't bother)
235   End of stalled plane case
236   BLANK
237   Set the temp x to the aiming plane's x value
238   Set the temp y to the aiming plane's y value
239   BLOCK START - Far aiming, if the target is further than 160 pixels...
240   If the object is moving left...
241   If the object has no hit count then...
242   Set its hit counter to 1 or 2 depending on altitude
243   Recursively aim up or down depending on the hit counter
244   Either up or down and set it for long aim
245   End case for left movement
246   Clear hitcounter
247   Otherwise, recursively aim 150 pixels in front..
248   And consider the plane's altitude..
249   along with course adjustment. Set for long shot
250   BLOCK END - Far aiming
251   If this isn't a far aim then...
252   Reset plane hitcount tracker
253   BLANK
254   If the aiming plane is moving...
255   Then apply course correction for minor y variances...
256   Push the object's start y towards zero
257   Otherwise we should check x
258   Correct for minor variances in x...
259   Push the x towards zero
260   BLANK
261   Copy the aiming object to the global temporary object structure. We're
      about to modify the copy for aiming projections from the real object
262   If the object is at max speed..
263   And is a plane...
264   Then set the temp speed variable to game max
265   Otherwise, it's not a plane or it's not moving
266   If the speed is somehow slower than game minimum
267   Set our temp speed variable to game minimum
268   BLANK
269   Remove target checks for now
270   BLOCK START - Test movement choices, Loop through all movement choices
271   The angle is the base angle...
272   Plus the positive or negative flat position
273   Wrapping the angles if necessary
274   Update the test plane's movement vector for its new angle
275   Perform a single move step along the new vector
276   Calculate the new range to target with the updated settings
277   Calculate the new altitude off the ground
278   Calculate the crash possibility
279   We've tracked the case to recopy the old one to test the next case
280   BLOCK END - Test movement choices
281   BLANK
282   BLANK
283   If the aim target is valid and the aimer has a good shot lined up..
284   If the plane has missiles...
285   Then set the missile target
286   Otherwise...
287   Fire the guns at the target
288   BLANK
289   Set the minimum range to a temp value
290   BLOCK START - Check for best range (positive), Loop through tested cases
291   If the tested range is positive...
292   But less than our test range..
293   and doesn't result in a crash
294   Then the new minimum range
295   Save best choice so far in n
296   BLOCK END - Check for best range (positive)
297   If the positive pass didn't result in a good choice...
298   Check the negative side
299   BLOCK START - Check for best range (negative), loop through tested cases
300   If the tested range is negative...
301   And is better than the temporary (or otherwise set case)
302   And the choice doesn't result in a crash...
303   Save this case as the new best
304   Save best choice in n
305   BLOCK END - Check for best range (negative)
306   End range check
307   BLANK
308   If the test plane's speed is too low
309   Change to maximum
310   BLANK
311   If a movement choice was found...
312   and the plane wasn't moving at max speed
313   Set it to max speed
314   Otherwise we didn't find a good movement choice to make, therefore
315   If the plane is accelerating...
316   Let off the gas
317   BLANK
318   Set the base choice to 0
319   If choice 1 had a higher altitude result,
320   Set the new altitude to that of the 1 case
321   Set the 1 case as the choice
322   End case for choosing 1
323   If the 2nd test choice beat one (or base)
324   Then choose case 2
325   End default AI movement choice
326   BLANK
327   Set the plane's flap position to the chosen case
328   If it is a plane and no change was made...
329   If the plane is moving...
330   Then fly the plane right side up (flip if necessary). Barrel roll!!
331   BLANK
332   BLOCK END - aim
333   BLANK
334   BLANK
335   BLANK
336   Declare static local target index anchors
337   BLANK
338   BLANK
339   BLANK

TEST FOR TARGETS
340   Declare cleartargs with no arguments
341   BLOCK START - cleartargs
342   Set targets left to -2
343   BLOCK END - cleartargs
344   BLANK
345   BLANK
346   BLANK
347   Declare testtargs with 2 arguments
348   Arguments are the x and y position of the tester (y is unused)
349   BLOCK START - testtargs, tests for possible target within input range
350   Declare local variables for index, target left x, and target right y
351   BLANK
352   x left is a point 32 pixels + difficulty game speed to the left of input
353   x right is 32 pixels + difficulty game speed to the right of input
354   BLANK
355   Set target left index to a temp value
356   Set target right index to a temp value
357   Loop through all targets to find the first valid target within range
358   If the target being checked has an x greater than our test window..
359   Set the target left index to the current loop index
360   End the loop
361   End target left check
362   BLANK
363   If no target left was found..
364   Then there can't possibly be a target right so end test
365   BLANK
366   Find the target right index starting where we left off
367   If the target is before the right hand window..
368   Set target right to i-1, since we've incremented already
369   BLOCK END - testtargs
370   BLANK
371   BLANK
372   BLANK
373   BLANK

TEST FOR CRASH
374   Declare tstcrash with four arguments
375   Arguments 2, 3, and 4 are x, y, and altitude above ground
376   Argument 1 is the pointer to the plane doing the test
377   BLOCK START - tstcrash, tests for possible collision with targets
378   Declare a local pointer to an object
379   Declare temporary x and y point tests
380   BLANK
381   If the input altitude is greater than 50...
382   ...then crashing isn't possible
383   BLANK
384   If the input altitude is below 22...
385   Then crashing must have occurred with the ground
386   BLANK
387   Point to the input plane
388   If target's haven't been checked...
389   Sweep the map for possible targets that may have been collided with
390   BLANK
391   Set xl to 32 pixels before the plane
392   Set xr to 32 pixels after the plane
393   BLANK
394   BLOCK START - Sweep through candidate targets, set from testtarg
395   If the the target is before the plane...
396   Then we missed, so continue sweep to next target
397   If the target is beyond our right side..
398   Then we also missed and there's no more targets, return false
399   A standing building is 16 pixels tall but a destroyed building is 8
400   If the plane is below the building height...
401   Then we crashed
402   BLOCK END - Sweep through candidate targets
403   We're here so we didnt' find a target
404   BLOCK END - tstcrash
405   BLANK
406   BLANK
407   BLANK
408   BLANK
409   BLANK

RANGE CHECK
410   Declare range with four arguments
411   Arguments are the origin (x,y) and the target (x,y)
412   BLOCK START - range, checks for range to target
413   Declare local integers for delta x and y
414   Declare a local temporary swap variable
415   BLANK
416   Delta y is the absolute value of the difference of origin and target y
417   Add 50% to delta y
418   If both delta x and delta y are less than 125..
419   Then return the total distance
420   BLANK
421   But, if the target is far above or below the plane...
422   Save x to temporary
423   Swap y
424   Swap x
425   End case for vertical check
426   BLANK
427   Return the distance to compensate for the screen aspect
428   BLOCK END - range
429   EOF