program spaceship (input,output); const MAX_PX = 68; MAX_PY = 19; MAXENTRY = 100; (* max # of inputs in path *) ACCURACY = 100; (* factor of extra calculations *) RADIUS = 1.0; type Vector = record x : real; y : real; end; var shipPos, massPos, velocity : Vector; numCalc : integer; mass, simTime: real; myCourse : array[1..MAXENTRY] of Vector; avgCourse : array[1..MAXENTRY] of Vector; procedure readEnvironment; begin readln(shipPos.x, shipPos.y); readln(velocity.x, velocity.y); readln(mass, massPos.x, massPos.y); readln(simTime, numCalc); if (numCalc > MAXENTRY) then writeln('Too many calculation points'); end; procedure calcPosition ( var shipPos, velocity : Vector; interval : real ) ; var deltaD, deltaV : Vector; distanceSquared, distance, speed : real; begin (* calculate distance to mass *) deltaD.x := massPos.x - shipPos.x; deltaD.y := massPos.y - shipPos.y; distanceSquared := deltaD.x*deltaD.x + deltaD.y*deltaD.y; distance := sqrt(distanceSquared); if (distance > RADIUS) then begin (* calculate change in velocity *) speed := interval * mass / distanceSquared; deltaV.x := speed * (deltaD.x / distance); deltaV.y := speed * (deltaD.y / distance); (* calculate new position using average velocity in interval *) shipPos.x := shipPos.x + ((velocity.x + deltaV.x/2) * interval); shipPos.y := shipPos.y + ((velocity.y + deltaV.y/2) * interval); (* calculate new velocity *) velocity.x := velocity.x + deltaV.x; velocity.y := velocity.y + deltaV.y; end; end; procedure calcAverageCourse ( ship, vel : Vector ) ; var interval, time : real; i, j : integer; begin time := 0.0; interval := simTime / numCalc; for i := 1 to numCalc do begin time := time + interval; calcPosition(ship, vel, interval); avgCourse[i] := ship; end; end; procedure calcAccurateCourse ( ship, vel : Vector ) ; var interval, time : real; i, j : integer; begin time := 0.0; interval := simTime / numCalc; for i := 1 to numCalc do begin time := time + interval; for j := 1 to ACCURACY do begin calcPosition(ship, vel, interval/ACCURACY); end; myCourse[i] := ship; end; end; function mapchar( inp : integer ; base : char ) : char; var c : char ; i, r : integer; begin i := inp mod 27; r := (inp div 27) mod 10; if (i = 0) then c := chr(ord('1') + r - 1) else c := chr(ord(base) + i - 1); mapchar := c; end; procedure plotCourse; var map : array[1..MAX_PX,1..MAX_PY] of char; course : array[1..MAXENTRY] of Vector; i, j, x, y, points : integer; min_x, max_x, min_y, max_y, pos_x, pos_y, time, grid_x, grid_y : real; num : real; deltaD : Vector; distance, accDistance, avgDistance: real; begin for i := 1 to MAX_PX do begin for j := 1 to MAX_PY do begin map[i,j] := ' '; end; end; min_x := myCourse[1].x; max_x := min_x; min_y := myCourse[i].y; max_y := min_y; time := 1.0; points := 0; (* read in input course *) while (time > 0.0) and (not eof) and (points <= numCalc) do begin readln(time, pos_x, pos_y); if (time > 0.0) then begin points := points + 1; course[points].x := pos_x; course[points].y := pos_y; if (pos_x < min_x) then min_x := pos_x; if (pos_x > max_x) then max_x := pos_x; if (pos_y < min_y) then min_y := pos_y; if (pos_y > max_y) then max_y := pos_y; end; end; (* calculate average course *) for i := 1 to numCalc do begin pos_x := avgCourse[i].x; pos_y := avgCourse[i].y; if (pos_x < min_x) then min_x := pos_x; if (pos_x > max_x) then max_x := pos_x; if (pos_y < min_y) then min_y := pos_y; if (pos_y > max_y) then max_y := pos_y; end; (* calculate more accurate course *) for i := 1 to numCalc do begin pos_x := myCourse[i].x; pos_y := myCourse[i].y; if (pos_x < min_x) then min_x := pos_x; if (pos_x > max_x) then max_x := pos_x; if (pos_y < min_y) then min_y := pos_y; if (pos_y > max_y) then max_y := pos_y; end; (* set up grid *) grid_x := (max_x - min_x) / MAX_PX; grid_y := (max_y - min_y) / MAX_PY; (* add space at edges *) grid_x := grid_x * 1.05; grid_y := grid_y * 1.05; min_x := min_x * 1.05; min_y := min_y * 1.05; if (grid_x < 0.0) then grid_x := - grid_x; if (grid_x = 0.0) then grid_x := 1.0; if (grid_x < 0.01) then grid_x := 0.01; if (grid_y < 0.0) then grid_y := - grid_y; if (grid_y = 0.0) then grid_y := 1.0; if (grid_y < 0.01) then grid_y := 0.01; (* map average course *) for i := 1 to numCalc do begin x := round( (myCourse[i].x - min_x) / grid_x) + 1; y := round( (myCourse[i].y - min_y) / grid_y) + 1; if (x > MAX_PX) then x := MAX_PX; if (x < 1) then x := 1; if (y > MAX_PY) then y := MAX_PY; if (y < 1) then y := 1; map[x,y] := '.'; end; (* map accurate course *) for i := 1 to numCalc do begin x := round( (myCourse[i].x - min_x) / grid_x) + 1; y := round( (myCourse[i].y - min_y) / grid_y) + 1; if (x > MAX_PX) then x := MAX_PX; if (x < 1) then x := 1; if (y > MAX_PY) then y := MAX_PY; if (y < 1) then y := 1; map[x,y] := mapchar(i,'A'); end; (* map input course *) for i := 1 to points do begin x := round( (course[i].x - min_x) / grid_x) + 1; y := round( (course[i].y - min_y) / grid_y) + 1; if (x > MAX_PX) then x := MAX_PX; if (x < 1) then x := 1; if (y > MAX_PY) then y := MAX_PY; if (y < 1) then y := 1; map[x,y] := mapchar(i,'a'); end; (* map position of planet *) x := round( (massPos.x - min_x) / grid_x) + 1; y := round( (massPos.y - min_y) / grid_y) + 1; if (x <= MAX_PX) and (x >= 1) and (y <= MAX_PY) and (y >= 1) then map[x,y] := '$'; (* output map *) write(' '); for i := 1 to MAX_PX do begin if (((i-2) mod 5) = 0) then begin num := (min_x + (i-1)*grid_x); write (num:5:1); end; end; writeln; (* write(' ------------------------------'); writeln('---------------------------------------'); *) for j := MAX_PY downto 1 do begin num := (min_y + (j-1)*grid_y); write (num:6:2, '|'); for i := 1 to MAX_PX do begin write (map[i,j]); end; writeln; end; (* calculate difference in final position *) writeln('Position:', ' (usr) ', course[points].x:8:3, course[points].y:8:3 , ' (avg) ', avgCourse[numCalc].x:8:3, avgCourse[numCalc].y:8:3 , ' (acc) ', myCourse[numCalc].x:8:3, myCourse[numCalc].y:8:3 ); deltaD.x := avgCourse[numCalc].x - course[points].x; deltaD.y := avgCourse[numCalc].y - course[points].y; avgDistance := sqrt(deltaD.x*deltaD.x + deltaD.y*deltaD.y); deltaD.x := myCourse[numCalc].x - course[points].x; deltaD.y := myCourse[numCalc].y - course[points].y; accDistance := sqrt(deltaD.x*deltaD.x + deltaD.y*deltaD.y); writeln('Error distance between user and: (avg) ', avgDistance:8:3, ' (acc) ', accDistance:8:3 ); end; begin readEnvironment; calcAverageCourse( shipPos, velocity ) ; calcAccurateCourse( shipPos, velocity ) ; plotCourse; end.