with TEXT_IO ; use TEXT_IO ; with HW7PKG ; use HW7PKG ; procedure HW7 is DUMMY : CHARACTER ; ESC_CHAR : CHARACTER := ASCII.ESC ; ESC_STR : STRING(1..4) := " [2J" ; begin ESC_STR(1) := ESC_CHAR ; PUT(ESC_STR) ; TARGET.ZOOM ; -- GET(DUMMY) ; -- This should allow target to fly, but it doesn't while T < 1.2 loop PUT(" ") ; -- poor mans delay end loop ; PLANE.FLY ; -- GET(DUMMY) ; -- This should allow plane to fly, but it doesn't while T < 2.6 loop PUT(" ") ; -- poor mans delay end loop ; MISSILE.ZIP ; while T < 8.0 loop -- T is time from package HW7PKG. PUT(" "); -- This loop keeps the main program alive. end loop ; -- The PUT provides for the control to get to the tasks end HW7 ; -- This seems to be needed to prevent terminate in -- the Select loop. with FLOAT_MATH_LIB ; use FLOAT_MATH_LIB ; with TEXT_IO ; use TEXT_IO , INTEGER_IO , FLOAT_IO ; package HW7PKG is T : FLOAT := 0.0 ; -- Global to all tasks and main program task TARGET is -- TASK SPECIFICATION FOR TARGET entry ZOOM ; end TARGET ; task PLANE is -- TASK SPECIFICATION FOR PLANE entry FLY ; end PLANE ; task MISSILE is -- TASK SPECIFICATION FOR MISSILE entry ZIP ; end MISSILE ; task SHARED is -- SHARED TASK SPECIFICATION entry REPORT (WHO:INTEGER ; X,Y,VX,VY:FLOAT) ; entry READ_OUT (WHO:INTEGER ; X,Y,VX,VY: out FLOAT) ; end SHARED ; end HW7PKG ; package body HW7PKG is task body TARGET is -- TASK BODY FOR TARGET TGT_X : FLOAT ; TGT_Y : FLOAT ; TGT_VX : FLOAT ; TGT_VY : FLOAT ; TGT_XOLD : FLOAT ; TGT_YOLD : FLOAT ; I : INTEGER ; J : INTEGER ; ESC_CHAR : CHARACTER := ASCII.ESC ; ESC_STR : STRING(1..1) ; begin accept ZOOM do null ; -- Go immediately to parallel execution end ; while T < 8.0 loop -- This is the timing loop T := T + 0.03 ; TGT_XOLD := TGT_X ; TGT_YOLD := TGT_Y ; TGT_X := COS(1.0*T) + 1.0 ; TGT_Y := SIN(1.0*T) + 1.0 ; TGT_VX := TGT_X - TGT_XOLD ; TGT_VY := TGT_Y - TGT_YOLD ; SHARED.REPORT(1,TGT_X,TGT_Y,TGT_VX,TGT_VY) ; ESC_STR(1) := ESC_CHAR ; I := INTEGER(TGT_X * 10.0 ) ; J := INTEGER(TGT_Y * 30.0 ) ; PUT(ESC_STR & "[" & INTEGER'IMAGE(I) &";"& INTEGER'IMAGE(J)&"f*") ; end loop ; end TARGET ; task body PLANE is -- TASK BODY FOR PLANE PLANE_X : FLOAT := 2.2 ; PLANE_Y : FLOAT := 0.0 ; PLANE_VX : FLOAT := 0.0 ; PLANE_VY : FLOAT := 0.0 ; PLANE_XOLD : FLOAT ; PLANE_YOLD : FLOAT ; TGT_X : FLOAT ; TGT_Y : FLOAT ; TGT_VX : FLOAT ; TGT_VY : FLOAT ; RANGE_TP : FLOAT ; I : INTEGER := 0 ; J : INTEGER := 0 ; ESC_CHAR : CHARACTER := ASCII.ESC ; ESC_STR : STRING(1..1) ; begin accept FLY do null ; end ; while T < 8.0 loop PLANE_XOLD := PLANE_X ; PLANE_YOLD := PLANE_Y ; SHARED.READ_OUT(1,TGT_X,TGT_Y,TGT_VX,TGT_VY) ; RANGE_TP := SQRT((TGT_X-PLANE_X)**2 + (TGT_Y-PLANE_Y)**2); if RANGE_TP < 0.2 then T := 999.0 ; PUT("crash"); end if ; PLANE_VX := (TGT_X - PLANE_X) / RANGE_TP ; PLANE_VY := (TGT_Y - PLANE_Y) / RANGE_TP ; PLANE_X := PLANE_X + 0.03 * PLANE_VX + 0.25 * TGT_VX ; PLANE_Y := PLANE_Y + 0.03 * PLANE_VY + 0.25 * TGT_VY ; PLANE_VX := PLANE_X - PLANE_XOLD ; PLANE_VY := PLANE_Y - PLANE_YOLD ; SHARED.REPORT (2,PLANE_X,PLANE_Y,PLANE_VX,PLANE_VY) ; ESC_STR(1) := ESC_CHAR ; I := INTEGER(PLANE_X * 10.0 ) ; J := INTEGER(PLANE_Y * 30.0 ) ; PUT(ESC_STR & "[" & INTEGER'IMAGE(I)&";"&INTEGER'IMAGE(J)&"f0") ; end loop ; end PLANE ; task body MISSILE is -- TASK BODY FOR MISSILE MIS_X : FLOAT ; MIS_Y : FLOAT ; MIS_VX : FLOAT ; MIS_VY : FLOAT ; PLANE_X : FLOAT ; PLANE_Y : FLOAT ; PLANE_VX : FLOAT ; PLANE_VY : FLOAT ; TGT_X : FLOAT ; TGT_Y : FLOAT ; TGT_VX : FLOAT ; TGT_VY : FLOAT ; RANGE_TM : FLOAT ; I : INTEGER := 0 ; J : INTEGER := 0 ; ESC_CHAR : CHARACTER := ASCII.ESC ; ESC_STR : STRING(1..1) ; begin accept ZIP do SHARED.READ_OUT(2,PLANE_X,PLANE_Y,PLANE_VX,PLANE_VY) ; MIS_X := PLANE_X + 0.1 * PLANE_VX ; MIS_Y := PLANE_Y + 0.1 * PLANE_VY ; end ; while T < 8.0 loop SHARED.READ_OUT(1,TGT_X,TGT_Y,TGT_VX,TGT_VY) ; RANGE_TM := SQRT((TGT_X-MIS_X)**2 + (TGT_Y-MIS_Y)**2); if RANGE_TM < 0.2 then T := 999.0 ; PUT("HIT"); end if ; MIS_VX := (TGT_X - MIS_X) / RANGE_TM ; MIS_VY := (TGT_Y - MIS_Y) / RANGE_TM ; MIS_X := MIS_X + 0.09 * MIS_VX ; MIS_Y := MIS_Y + 0.09 * MIS_VY ; ESC_STR(1) := ESC_CHAR ; I := INTEGER(MIS_X * 10.0 ) ; J := INTEGER(MIS_Y * 30.0 ) ; PUT(ESC_STR & "[" & INTEGER'IMAGE(I)&";"&INTEGER'IMAGE(J)&"f+") ; end loop ; end MISSILE ; task body SHARED is -- SHARED TASK BODY type SH_VEC is array(1..2) of FLOAT ; X_VALS : SH_VEC ; Y_VALS : SH_VEC ; VX_VALS : SH_VEC ; VY_VALS : SH_VEC ; begin loop select accept REPORT (WHO:INTEGER ; X,Y,VX,VY:FLOAT) do X_VALS(WHO) := X ; Y_VALS(WHO) := Y ; VX_VALS(WHO) := VX ; VY_VALS(WHO) := VX ; end ; or accept READ_OUT (WHO:INTEGER ; X,Y,VX,VY: out FLOAT) do X := X_VALS(WHO) ; Y := Y_VALS(WHO) ; VX := VX_VALS(WHO) ; VY := VY_VALS(WHO) ; end ; or terminate ; end select ; end loop ; end SHARED ; end HW7PKG ; NOTES: Different compilers will have different algorithms for context switching while tasking. TELESOFT seems to stay in a task ( including the main procedure as long as computation is possible. The context switch occurs when any form of PUT is executed. I/O takes a relatively long time, thus if one task has output then all parallel tasks that must be kept running must also have output ( or must be locked from execution some other way ). The main procedure is the sponsor of the SHARED task and thus must be kept running until the TARGET, PLANE, and MISSILE task are complete. The global time T is used to synchronize all tasks and main program termination. Any code can set T to a large number to stop the process. This works reliably because the only other action to change T is to increment it. It would seem reasonable if GET would suspend waiting for input and let parallel task run. It doesn't! The entries SHARED.REPORT and SHARED.READ_OUT are to ensure that the four values X,Y,VX,VY are a consistant set independent of the context switching algorithm. This is the standard Ada construct for shared data. The equations and constants for moving the TARGET, PLANE, and MISSILE were determined by experimenting. The PLANE is using a lead angle based on the TARGET velocity vector. The MISSILE just keeps going for the present TARGET position. The accept ZIP is the only time the MISSILE uses the PLANE's data ( launch ). The PLANE can stop the run if it crashes into the TARGET. The MISSILE stops the run when it hits the TARGET.