gravwars.pp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. Program GravityWars;
  2. {A demo for TP 4.0 compability of Graph.
  3. The sources for this game was found on a site that claims to only have
  4. PD stuff with the below header(which was only reindented), and the webmaster
  5. said that everything he published was sent to him with that purpose. We tried
  6. to contact the authors mentioned below via mail over internet, but that
  7. failed. If there is somebody that claims authorship of these programs,
  8. please mail [email protected], and the sources will be removed from our
  9. websites.
  10. ------------------------------------------------------------------------
  11. ORIGINAL Header:
  12. by Sohrab Ismail-Beigi Completed 4/23/89
  13. SYSOP of The 3D Graphics BBS
  14. 300/1200/2400 baud, N-8-1 Full duplex
  15. (201) 444-4154
  16. Turbo Pascal 4.0 source code. Requires VGA 640x480x16 display.
  17. Note: pix=pixels in the comments}
  18. Uses Crt,Graph;
  19. Type
  20. spacecraft=Record {used for ships and pointer}
  21. coffx,coffy,r : longint; {center offsets and radius in pix}
  22. imagex,imagey : longint; {upper left of image}
  23. imagepointr : pointer; {pointer to image data}
  24. imagesize : word; {size in bytes}
  25. end;
  26. planettype=Record
  27. cx,cy,r : longint; {planet center and radius}
  28. d,GM : real; {density and G*M product}
  29. end;
  30. Const
  31. color : array[1..3] of byte=(Red,Green,LightBlue); {colors for planets}
  32. G=0.1; {gravity constant}
  33. bhr=15; {black hole radius}
  34. Esc=#27; {ASCII for Esc}
  35. Return=#13; { " " RETURN}
  36. Var
  37. ship : array[1..2] of spacecraft; {2 ships}
  38. tp,pointr : spacecraft; {tp is temporary, 1 pointer}
  39. pl : array[1..9] of planettype; {the 9 planets}
  40. screen : Record {the game area}
  41. sx,ex,sy,ey,cx,cy,lx,ly : longint; {start x/y, end x/y, center}
  42. end; {x/y, length x/y}
  43. np,GraphDriver,GraphMode : integer; {# of planets}
  44. criticaldist : real; {for escape velocity calc}
  45. playsong : boolean; {play the songs?}
  46. Procedure Init; {initialize everything}
  47. begin
  48. //SetGraphBufSize(10);
  49. GraphDriver:=VGA;
  50. GraphMode:=VGAHi;
  51. InitGraph(GraphDriver,GraphMode,'');
  52. setbkcolor(black);
  53. setviewport(0,0,getmaxx,getmaxy,clipoff);
  54. clearviewport;
  55. SetColor(LightGray);
  56. SetFillStyle(SolidFill,LightGray); {Hull of ships}
  57. Circle(100,100,9);
  58. FloodFill(100,100,LightGray);
  59. Bar(77,98,100,102);
  60. MoveTo(82,98);
  61. LineRel(-3,-8);
  62. LineRel(-13,0); LineRel(0,-3);
  63. LineRel(24,0); LineRel(0,3);
  64. LineRel(-7,0); LineRel(3,8);
  65. FloodFill(83,97,LightGray);
  66. MoveTo(82,101); LineRel(-3,8);
  67. LineRel(-13,0); LineRel(0,3);
  68. LineRel(24,0); LineRel(0,-3);
  69. LineRel(-7,0); LineRel(3,-8);
  70. FloodFill(83,103,LightGray);
  71. MoveTo(200,200); LineRel(5,-5);
  72. LineRel(5,5); LineRel(10,0);
  73. LineRel(5,-8); LineRel(15,0);
  74. LineRel(-6,9); LineRel(6,9);
  75. LineRel(-15,0); LineRel(-5,-7);
  76. LineRel(-10,0); LineRel(-5,5);
  77. LineRel(-6,-7); LineRel(2,-2);
  78. FloodFill(201,201,LightGray);
  79. SetColor(LightRed);
  80. SetFillStyle(SolidFill,LightRed); {Red lights on ships}
  81. Circle(100,100,2);
  82. FloodFill(100,100,LightRed);
  83. Bar(89,87,91,90); Bar(89,109,91,112);
  84. Bar(224,200,226,203); Bar(240,192,242,194);
  85. Bar(240,208,242,210);
  86. SetColor(Yellow);
  87. MoveTo(0,0); LineRel(0,10);
  88. MoveTo(0,0); LineRel(10,0);
  89. MoveTo(0,0); LineRel(15,15); {pointer}
  90. tp.imagesize:=ImageSize(0,0,16,16); {kludge to subdue compiler bug}
  91. GetMem(tp.imagepointr,tp.imagesize);
  92. GetImage(0,0,16,16,tp.imagepointr^);
  93. pointr.imagesize:=ImageSize(0,0,16,16);
  94. GetMem(pointr.imagepointr,pointr.imagesize);
  95. GetImage(0,0,16,16,pointr.imagepointr^); {get pointer}
  96. pointr.coffx:=7;
  97. pointr.coffy:=7;
  98. pointr.r:=9;
  99. ship[1].imagesize:=ImageSize(66,87,110,113);
  100. GetMem(ship[1].imagepointr,ship[1].imagesize);
  101. GetImage(66,87,110,113,ship[1].imagepointr^); {enterprise}
  102. ship[1].coffx:=22; ship[1].coffy:=13; ship[1].r:=26;
  103. ship[2].imagesize:=ImageSize(199,192,242,210);
  104. GetMem(ship[2].imagepointr,ship[2].imagesize);
  105. GetImage(199,192,242,210,ship[2].imagepointr^); {klingon}
  106. ship[2].coffx:=21; ship[2].coffy:=9; ship[2].r:=23;
  107. ClearDevice;
  108. screen.sx:=1;
  109. screen.ex:=638;
  110. screen.sy:=33;
  111. screen.ey:=478;
  112. screen.cx:=(screen.sx+screen.ex) div 2; {initialize screen}
  113. screen.cy:=(screen.sy+screen.ey) div 2; {bounds}
  114. screen.lx:=screen.ex-screen.sx+1;
  115. screen.ly:=screen.ey-screen.sy+1;
  116. criticaldist:=2.0*sqrt(sqr(screen.lx)+sqr(screen.ly)); {critical distance}
  117. playsong:=true; {for escape vel. calc}
  118. end;
  119. Procedure Finish; {free memory and end}
  120. begin
  121. FreeMem(ship[1].imagepointr,ship[1].imagesize);
  122. FreeMem(ship[2].imagepointr,ship[2].imagesize);
  123. FreeMem(pointr.imagepointr,pointr.imagesize);
  124. FreeMem(tp.imagepointr,tp.imagesize);
  125. CloseGraph;
  126. end;
  127. Function InBounds(cx,cy,r:longint):boolean; {is the point with radius}
  128. begin {completely in screen bounds?}
  129. InBounds:=true;
  130. if r<>0 then
  131. if (cx-r<=screen.sx) or (cx+r>=screen.ex) or
  132. (cy-r<=screen.sy) or (cy+r>=screen.ey) then
  133. InBounds:=false
  134. else
  135. if (cx-bhr<=screen.sx) or (cx+bhr>=screen.ex) or
  136. (cy-bhr<=screen.sy) or (cy+bhr>=screen.ey) then
  137. InBounds:=false;
  138. end;
  139. Procedure RandomSetup; {make a random setup}
  140. var i,j : integer;
  141. a,b : longint;
  142. ok : boolean;
  143. begin
  144. Randomize;
  145. np:=Random(9)+1; {random # of planets 1-9}
  146. for i:=1 to np do {pick planet positions}
  147. Repeat
  148. ok:=true;
  149. pl[i].cx:=Random(screen.lx)+screen.sx;
  150. pl[i].cy:=Random(screen.ly)+screen.sy;
  151. pl[i].d:=(Random(3)+2)/2.0;
  152. pl[i].r:=0;
  153. if Random>0.05 then pl[i].r:=Random(70)+20; {5% chance of blackhole}
  154. if pl[i].r<>0 then
  155. pl[i].GM:=G*2*pi*sqr(pl[i].r)*pl[i].d
  156. else
  157. pl[i].GM:=G*2*pi*sqr(30)*1.0;
  158. ok:=InBounds(pl[i].cx,pl[i].cy,pl[i].r);
  159. if (i>1) and (ok) then {any collisions with existing planets?}
  160. for j:=1 to i-1 do
  161. begin
  162. if sqrt(sqr(pl[i].cx-pl[j].cx)+sqr(pl[i].cy-pl[j].cy))<=
  163. pl[i].r+pl[j].r+2*bhr then
  164. ok:=false;
  165. end;
  166. Until ok;
  167. for i:=1 to 2 do {pick ship positions}
  168. Repeat
  169. ok:=true;
  170. ship[i].imagex:=Random(screen.lx div 2)+screen.sx; {enterprise to the}
  171. if i=2 then ship[2].imagex:=ship[i].imagex+screen.lx div 2; {left and}
  172. ship[i].imagey:=Random(screen.ly)+screen.sy; {klingon to the right}
  173. a:=ship[i].imagex+ship[i].coffx; b:=ship[i].imagey+ship[i].coffy;
  174. ok:=InBounds(a,b,ship[i].r);
  175. for j:=1 to np do {any collisions with planets?}
  176. if sqrt(sqr(a-pl[j].cx)+sqr(b-pl[j].cy))<=pl[j].r+ship[i].r+bhr then
  177. ok:=false;
  178. Until ok;
  179. end;
  180. Procedure DrawSetup; {draw current setup}
  181. var i,j : integer;
  182. begin
  183. ClearDevice;
  184. SetColor(White);
  185. Rectangle(screen.sx-1,screen.sy-1,screen.ex-1,screen.ey-1); {game box}
  186. for i:=1 to 2000 do {2000 random stars}
  187. PutPixel(Random(screen.lx)+screen.sx,Random(screen.ly)+screen.sy,White);
  188. for i:=1 to 2 do {2 ships}
  189. PutImage(ship[i].imagex,ship[i].imagey,ship[i].imagepointr^,NormalPut);
  190. for i:=1 to np do {np planets}
  191. if pl[i].r>0 then {normal}
  192. begin
  193. SetColor(color[trunc(pl[i].d*2-1)]);
  194. Circle(pl[i].cx,pl[i].cy,pl[i].r);
  195. SetFillStyle(SolidFill,color[trunc(pl[i].d*2-1)]);
  196. FloodFill(pl[i].cx,pl[i].cy,color[trunc(pl[i].d*2-1)]);
  197. end
  198. else {black hole}
  199. begin
  200. SetColor(Black);
  201. for j:=0 to bhr do
  202. Circle(pl[i].cx,pl[i].cy,j);
  203. end;
  204. end;
  205. Procedure ClearDialogBox; {clear text message area}
  206. begin
  207. SetFillStyle(SolidFill,Black);
  208. Bar(0,0,screen.ex-1,screen.sy-2);
  209. end;
  210. Function GetString:string; {get a string until RETURN is pressed}
  211. var s : string;
  212. c : char;
  213. begin
  214. s:='';
  215. Repeat
  216. c:=ReadKey;
  217. if (c=chr(8)) and (length(s)>0) then {backspace key}
  218. begin
  219. delete(s,length(s),1);
  220. MoveRel(-8,0); {delete last char}
  221. SetFillStyle(SolidFill,Black);
  222. Bar(GetX,GetY,GetX+8,GetY+8);
  223. end
  224. else if c<>Return then
  225. begin
  226. s:=concat(s,c); {get and draw char}
  227. SetColor(LightGray);
  228. OutText(c);
  229. end;
  230. Until c=Return;
  231. GetString:=s;
  232. end;
  233. Procedure PlayGame;
  234. Const number_of_explosion_dots=20; {# dots for explosion with planet surface}
  235. Var vx,vy,vc,x,y,dt,ax,ay,dx,dy,dr,k : real;
  236. v0,angle : array[1..2] of real;
  237. s : string;
  238. ch : char;
  239. i,event,player,winner : integer;
  240. ok,donecritical,offscreen : boolean;
  241. buffer : array[1..number_of_explosion_dots] of Record {for explosion}
  242. x,y,color : integer;
  243. end;
  244. begin
  245. v0[1]:=0; v0[2]:=0; angle[1]:=0; angle[2]:=0;
  246. player:=1;
  247. donecritical:=false;
  248. Repeat {infinite loop}
  249. ClearDialogBox;
  250. SetColor(LightGray);
  251. str(player,s);
  252. s:=concat('Player ',s); {player #}
  253. OutTextXY(0,0,s);
  254. Repeat {get angle}
  255. MoveTo(0,10);
  256. str(angle[player]:3:5,s);
  257. s:=concat('Angle: [',s,']: ');
  258. OutText(s);
  259. s:=GetString;
  260. if (s[1]='Q') or (s[1]='q') then exit;
  261. i:=0;
  262. if s<>'' then Val(s,angle[player],i);
  263. SetFillStyle(SolidFill,Black);
  264. ok:=(i=0) and (angle[player]>=0.0) and (angle[player]<=360);
  265. if not ok then Bar(0,10,screen.ex-1,18);
  266. Until ok;
  267. Repeat {get initial velocity}
  268. MoveTo(0,20);
  269. str(v0[player]:2:5,s);
  270. s:=concat('Initial Velocity: [',s,']: ');
  271. OutText(s);
  272. s:=GetString;
  273. if (s[1]='Q') or (s[1]='q') then exit;
  274. i:=0;
  275. if s<>'' then Val(s,v0[player],i);
  276. SetFillStyle(SolidFill,Black);
  277. ok:=(i=0) and (v0[player]>=0.0) and (v0[player]<=10.0);
  278. if not ok then Bar(0,20,screen.ex-1,28);
  279. Until ok;
  280. k:=pi*angle[player]/180.0; {angle in radians}
  281. vx:=v0[player]*cos(k);
  282. vy:=-v0[player]*sin(k);
  283. x:=ship[player].imagex+ship[player].coffx+ship[player].r*cos(k);
  284. y:=ship[player].imagey+ship[player].coffy-ship[player].r*sin(k);
  285. ClearDialogBox;
  286. MoveTo(round(x),round(y));
  287. SetColor(White);
  288. offscreen:=false;
  289. Repeat {calculate and draw trajectory}
  290. dt:=0.25; {time interval [vel. is in pix/time]}
  291. x:=x+vx*dt; y:=y+vy*dt;
  292. ax:=0; ay:=0;
  293. for i:=1 to np do {calc accel. due to gravity}
  294. begin
  295. dx:=x-pl[i].cx; dy:=y-pl[i].cy; dr:=sqrt(sqr(dx)+sqr(dy));
  296. k:=1/(sqr(dr)*dr);
  297. if pl[i].r<>0 then {normal}
  298. begin
  299. ax:=ax-pl[i].GM*dx*k;
  300. ay:=ay-pl[i].GM*dy*k
  301. end
  302. else {black hole}
  303. begin
  304. ax:=ax-pl[i].GM*dx*(k+sqr(k*dr));
  305. ay:=ay-pl[i].GM*dy*(k+sqr(k*dr));
  306. end;
  307. end;
  308. vx:=vx+ax*dt; vy:=vy+ay*dt;
  309. event:=0;
  310. if keypressed then
  311. event:=1
  312. else if (x>=screen.sx) and (x<=screen.ex) and {in screen bounds?}
  313. (y>=screen.sy) and (y<=screen.ey) then
  314. begin
  315. donecritical:=false;
  316. i:=GetPixel(round(x),round(y));
  317. if (i=color[1]) or (i=color[2]) or (i=color[3]) or
  318. (i=LightRed) or (i=LightGray) then event:=2
  319. else
  320. if offscreen then
  321. MoveTo(round(x),round(y))
  322. else
  323. LineTo(round(x),round(y));
  324. offscreen:=false;
  325. end {off screen}
  326. else if not donecritical then
  327. begin
  328. offscreen:=true; {offscreen and critical distance}
  329. dx:=x-screen.cx; dy:=y-screen.cy; dr:=sqrt(sqr(dx)+sqr(dy));
  330. if dr>=criticaldist then
  331. begin
  332. vc:=(dx*vx+dy*vy)/dr;
  333. k:=0; for i:=1 to np do k:=k+pl[i].GM;
  334. if 0.5*sqr(vc)>=k/dr then {do we have escape velocity?}
  335. event:=3;
  336. end;
  337. end;
  338. Until event<>0;
  339. if event=1 then {a key was pressed for a break}
  340. begin
  341. ClearDialogBox;
  342. ch:=ReadKey; {one already in buffer}
  343. SetColor(LightGray);
  344. OutTextXY(0,0,'Break... Esc to break, any other key to continue');
  345. ch:=ReadKey;
  346. if ch=Esc then exit;
  347. end
  348. else if event=3 then {missile escaped the universe}
  349. begin
  350. ClearDialogBox;
  351. SetColor(LightGray);
  352. OutTextXY(0,0,'Missile left the galaxy...');
  353. delay(2000);
  354. end
  355. else {event=2} {hit something}
  356. begin
  357. if (i=color[1]) or (i=color[2]) or (i=color[3]) then {hit a planet}
  358. begin
  359. for i:=1 to number_of_explosion_dots do {draw explosion}
  360. begin
  361. buffer[i].x:=trunc(x+20*(Random-0.5));
  362. buffer[i].y:=trunc(y+20*(Random-0.5));
  363. buffer[i].color:=GetPixel(buffer[i].x,buffer[i].y);
  364. PutPixel(buffer[i].x,buffer[i].y,LightRed);
  365. delay(25);
  366. end;
  367. delay(1000);
  368. for i:=1 to number_of_explosion_dots do {erase explosion}
  369. PutPixel(buffer[i].x,buffer[i].y,buffer[i].color);
  370. end
  371. else {hit a ship!}
  372. begin
  373. if sqrt(sqr(x-ship[1].imagex-ship[1].coffx)+ {which one won?}
  374. sqr(y-ship[1].imagey-ship[1].coffy))<=ship[1].r+5 then
  375. winner:=2
  376. else winner:=1;
  377. for event:=1 to 100 do {flash the screen}
  378. SetPalette(Black,Random(16));
  379. SetPalette(Black,Black);
  380. for i:=1 to 1000 do {put some white and red points}
  381. begin
  382. k:=Random*2*pi;
  383. event:=Random(3);
  384. if event=0 then
  385. PutPixel(trunc(x+30*Random*cos(k)),trunc(y+30*Random*sin(k)),Black)
  386. else if event=1 then
  387. PutPixel(trunc(x+30*Random*cos(k)),trunc(y+30*Random*sin(k)),Red)
  388. else
  389. PutPixel(trunc(x+20*Random*cos(k)),trunc(y+20*Random*sin(k)),White);
  390. end;
  391. ClearDialogBox;
  392. SetColor(LightGray);
  393. str(winner,s);
  394. s:=concat('Player ',s,' wins!!!'); {announce}
  395. OutTextXY(0,0,s);
  396. if playsong then {play a tune}
  397. begin
  398. Sound(440); delay(150);
  399. Nosound; delay(50);
  400. Sound(440); delay(150);
  401. Sound(554); delay(150);
  402. Sound(659); delay(350);
  403. Sound(554); delay(150);
  404. Sound(659); delay(450);
  405. Nosound; delay(500);
  406. Sound(880); delay(800);
  407. Nosound;
  408. end;
  409. delay(3000);
  410. exit;
  411. end;
  412. end; {if event=3}
  413. Inc(player); if player=3 then player:=1; {next player}
  414. Until true=false; {infinite loop}
  415. end;
  416. Procedure PlayingtheGame; {playing the game menu}
  417. var option : char;
  418. begin
  419. Repeat
  420. ClearDialogBox;
  421. SetColor(LightGray);
  422. OutTextXY(0,0,'1. Random setup 2. Play game Esc quits menu');
  423. OutTextXY(0,10,'Option: ');
  424. option:=ReadKey;
  425. Case option of
  426. '1' : begin
  427. ClearDialogBox;
  428. RandomSetup;
  429. DrawSetup;
  430. end;
  431. '2' : PlayGame;
  432. end;
  433. Until option=Esc;
  434. end;
  435. Procedure Options; {options menu}
  436. var option : char;
  437. begin
  438. Repeat
  439. ClearDialogBox;
  440. SetColor(LightGray);
  441. OutTextXY(0,0,'1. Redraw screen 2. Sound on/off Esc quits menu');
  442. OutTextXY(0,10,'Option: ');
  443. option:=ReadKey;
  444. Case option of
  445. '1' : DrawSetUp;
  446. '2' : playsong:=not playsong;
  447. end;
  448. Until option=Esc;
  449. end;
  450. Procedure InterpKey(c:char; var x,y,coffx,coffy,r:longint;
  451. var jump:integer; var moveit:boolean);
  452. begin {interprets keys for movement of pointer, mainly to save}
  453. Case c of {space due to shared code in many Change routines}
  454. '+' : if jump<49 then Inc(jump,2);
  455. '-' : if jump>2 then Dec(jump,2);
  456. '8' : begin {up}
  457. Dec(y,jump);
  458. if InBounds(x+coffx,y+coffy,r) then
  459. moveit:=true
  460. else
  461. Inc(y,jump);
  462. end;
  463. '2' : begin {down}
  464. Inc(y,jump);
  465. if InBounds(x+coffx,y+coffy,r) then
  466. moveit:=true
  467. else
  468. Dec(y,jump);
  469. end;
  470. '4' : begin {left}
  471. Dec(x,jump);
  472. if InBounds(x+coffx,y+coffy,r) then
  473. moveit:=true
  474. else
  475. Inc(x,jump);
  476. end;
  477. '6' : begin {right}
  478. Inc(x,jump);
  479. if InBounds(x+coffx,y+coffy,r) then
  480. moveit:=true
  481. else
  482. Dec(x,jump);
  483. end;
  484. end; {case c of}
  485. end;
  486. Procedure MoveShip; {move a given ship to a new legal position}
  487. var c : char;
  488. s,jump,j : integer;
  489. x,y,xold,yold,a,b : longint;
  490. legal,moveit : boolean;
  491. begin
  492. ClearDialogBox;
  493. SetColor(LightGray);
  494. OutTextXY(0, 0,'Ships: 1. Enterprise 2. Klingon Esc aborts');
  495. OutTextXY(0,10,'Which ship? '); {get the proper ship}
  496. Repeat
  497. c:=ReadKey;
  498. Until (c='1') or (c='2') or (c=Esc);
  499. if c=Esc then exit;
  500. if c='1' then s:=1 else s:=2;
  501. ClearDialogBox;
  502. OutTextXY(0, 0,'Use cursors to move ship. (Num Lock on) Esc aborts');
  503. OutTextXY(0,10,'Enter to place, + and - to change size of jumps.');
  504. jump:=30;
  505. x:=ship[s].imagex; y:=ship[s].imagey;
  506. Repeat {loop until Esc or somewhere legal}
  507. Repeat {loop until Esc or RETURN}
  508. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  509. (c='+') or (c='-') or (c=Return) or (c=Esc);
  510. moveit:=false; xold:=x; yold:=y;
  511. InterpKey(c,x,y,ship[s].coffx,ship[s].coffy,ship[s].r,jump,moveit);
  512. if moveit then {if can move the image,}
  513. begin
  514. PutImage(xold,yold,ship[s].imagepointr^,XORPut); {erase old}
  515. PutImage(x,y,ship[s].imagepointr^,XORPut); {draw new}
  516. moveit:=false;
  517. end;
  518. Until (c=Return) or (c=Esc);
  519. if c=Esc then {abort}
  520. begin
  521. PutImage(x,y,ship[s].imagepointr^,XORPut);
  522. PutImage(ship[s].imagex,ship[s].imagey,ship[s].imagepointr^,NormalPut);
  523. exit;
  524. end;
  525. a:=x+ship[s].coffx; b:=y+ship[s].coffy;
  526. legal:=InBounds(a,b,ship[s].r); {in bounds?}
  527. for j:=1 to np do {in collision with any planets?}
  528. if sqrt(sqr(a-pl[j].cx)+sqr(b-pl[j].cy))<=pl[j].r+ship[s].r+bhr then
  529. legal:=false;
  530. if not legal then {oops! not legal!}
  531. begin
  532. SetPalette(Black,White);
  533. SetFillStyle(SolidFill,Black);
  534. Bar(0,20,screen.ex,screen.sy-2);
  535. delay(100);
  536. SetPalette(Black,Black);
  537. SetColor(LightGray);
  538. OutTextXY(0,20,'Illegal ship position!');
  539. end;
  540. Until legal;
  541. ship[s].imagex:=x; ship[s].imagey:=y; {ok, place it there}
  542. end;
  543. Procedure MovePlanet; {move a planet}
  544. var c : char;
  545. i,p,jump : integer;
  546. x,y,xold,yold,minr,t,cxorig,cyorig : longint;
  547. moveit,legal : boolean;
  548. begin
  549. ClearDialogBox;
  550. if np=0 then {no planets!}
  551. begin
  552. OutTextXY(0,0,'No planets to move!');
  553. delay(2000);
  554. exit;
  555. end;
  556. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  557. OutTextXY(0,10,'Enter to pick planet, + and - to change size of jumps.');
  558. jump:=30;
  559. x:=100; y:=100; PutImage(x,y,pointr.imagepointr^,XORPut);
  560. Repeat {loop until Esc or RETURN}
  561. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  562. (c='+') or (c='-') or (c=Return) or (c=Esc);
  563. moveit:=false; xold:=x; yold:=y;
  564. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  565. if moveit then
  566. begin
  567. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  568. PutImage(x,y,pointr.imagepointr^,XORPut);
  569. moveit:=false;
  570. end;
  571. Until (c=Return) or (c=Esc);
  572. PutImage(x,y,pointr.imagepointr^,XORPut); {erase pointer}
  573. if c=Esc then exit;
  574. p:=0; minr:=trunc(sqrt(sqr(screen.lx)+sqr(screen.ly)));
  575. for i:=1 to np do {find the closest planet/black hole}
  576. begin
  577. t:=trunc(sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy)));
  578. if t<minr then begin minr:=t; p:=i; end;
  579. end;
  580. SetColor(LightGreen); {clear it out}
  581. Circle(pl[p].cx,pl[p].cy,pl[p].r);
  582. SetFillStyle(SolidFill,Black);
  583. FloodFill(pl[p].cx,pl[p].cy,LightGreen);
  584. SetColor(Black);
  585. Circle(pl[p].cx,pl[p].cy,pl[p].r);
  586. ClearDialogBox;
  587. SetColor(LightGray);
  588. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  589. OutTextXY(0,10,'Enter to place planet center, + - change size of jumps.');
  590. jump:=30;
  591. x:=100; y:=100; PutImage(x,y,pointr.imagepointr^,XORPut);
  592. cxorig:=pl[p].cx; cyorig:=pl[p].cy; {save them as they may change later}
  593. Repeat {loop until Esc or legal position}
  594. Repeat
  595. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  596. (c='+') or (c='-') or (c=Return) or (c=Esc);
  597. moveit:=false; xold:=x; yold:=y;
  598. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  599. if moveit then
  600. begin
  601. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  602. PutImage(x,y,pointr.imagepointr^,XORPut);
  603. moveit:=false;
  604. end;
  605. Until (c=Return) or (c=Esc);
  606. legal:=true;
  607. if c<>Esc then {ok, RETURN pressed}
  608. begin
  609. pl[p].cx:=-1000; pl[p].cy:=-1000; {so it won't collide with itself!}
  610. for i:=1 to np do {any collisions with other planets?}
  611. if sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy))<=pl[i].r+pl[p].r+2*bhr then
  612. legal:=false;
  613. for i:=1 to 2 do {any collisions with other ships?}
  614. if sqrt(sqr(x-ship[i].imagex-ship[i].coffx)+
  615. sqr(y-ship[i].imagey-ship[i].coffy))<=pl[p].r+ship[i].r+bhr
  616. then legal:=false;
  617. end;
  618. if not legal then {oops!}
  619. begin
  620. SetPalette(Black,White);
  621. SetFillStyle(SolidFill,Black);
  622. Bar(0,20,screen.ex,screen.sy-2);
  623. delay(100);
  624. SetPalette(Black,Black);
  625. SetColor(LightGray);
  626. OutTextXY(0,20,'Illegal planet position!');
  627. end;
  628. Until legal;
  629. pl[p].cx:=x; pl[p].cy:=y; {put it there}
  630. if c=Esc then {abort and restore}
  631. begin
  632. pl[p].cx:=cxorig;
  633. pl[p].cy:=cyorig;
  634. end;
  635. DrawSetUp; {redraw screen}
  636. end;
  637. Procedure MakePlanet; {make a planet given center and radius}
  638. var c : char;
  639. i,p,jump : integer;
  640. x,y,xold,yold : longint;
  641. moveit,legal : boolean;
  642. begin
  643. ClearDialogBox;
  644. if np=9 then {too many planets already!}
  645. begin
  646. OutTextXY(0,0,'Can not make any more planets!');
  647. delay(2000);
  648. exit;
  649. end;
  650. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  651. OutTextXY(0,10,'Enter to place center, + and - to change size of jumps.');
  652. jump:=30;
  653. x:=100; y:=100; PutImage(x,y,pointr.imagepointr^,XORPut);
  654. Repeat {loop until a legal center is picked or Esc}
  655. Repeat
  656. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  657. (c='+') or (c='-') or (c=Return) or (c=Esc);
  658. moveit:=false; xold:=x; yold:=y;
  659. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  660. if moveit then
  661. begin
  662. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  663. PutImage(x,y,pointr.imagepointr^,XORPut);
  664. moveit:=false;
  665. end;
  666. Until (c=Return) or (c=Esc);
  667. if c=Esc then exit;
  668. legal:=true;
  669. for i:=1 to np do {any collisions with planets?}
  670. if sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy))<=pl[i].r+2*bhr then
  671. legal:=false;
  672. for i:=1 to 2 do {any collisions with ships?}
  673. if sqrt(sqr(x-ship[i].imagex-ship[i].coffx)+
  674. sqr(y-ship[i].imagey-ship[i].coffy))<=ship[i].r+bhr
  675. then legal:=false;
  676. if not legal then {uh oh!}
  677. begin
  678. SetPalette(Black,White);
  679. SetFillStyle(SolidFill,Black);
  680. Bar(0,20,screen.ex,screen.sy-2);
  681. delay(100);
  682. SetPalette(Black,Black);
  683. SetColor(LightGray);
  684. OutTextXY(0,20,'Illegal planet center!');
  685. end;
  686. Until legal;
  687. p:=np+1; pl[p].cx:=x; pl[p].cy:=y; {ok, store the info}
  688. ClearDialogBox;
  689. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  690. OutTextXY(0,10,'Enter to radius, + and - change size of jumps.');
  691. jump:=30;
  692. Repeat {loop until a legal radius is entered or Esc}
  693. Repeat
  694. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  695. (c='+') or (c='-') or (c=Return) or (c=Esc);
  696. moveit:=false; xold:=x; yold:=y;
  697. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  698. if moveit then
  699. begin
  700. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  701. PutImage(x,y,pointr.imagepointr^,XORPut);
  702. moveit:=false;
  703. end;
  704. Until (c=Return) or (c=Esc);
  705. if c=Esc then exit;
  706. legal:=true;
  707. pl[p].r:=round(sqrt(sqr(x-pl[p].cx)+sqr(y-pl[p].cy))); {find radius}
  708. for i:=1 to np do {planet collisions?}
  709. if sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy))<=pl[p].r+pl[i].r+2*bhr then
  710. legal:=false;
  711. for i:=1 to 2 do {ship collisions?}
  712. if sqrt(sqr(x-ship[i].imagex-ship[i].coffx)+
  713. sqr(y-ship[i].imagey-ship[i].coffy))<=pl[p].r+ship[i].r+bhr
  714. then legal:=false;
  715. if not legal then {oh no!}
  716. begin
  717. SetPalette(Black,White);
  718. SetFillStyle(SolidFill,Black);
  719. Bar(0,20,screen.ex,screen.sy-2);
  720. delay(100);
  721. SetPalette(Black,Black);
  722. SetColor(LightGray);
  723. OutTextXY(0,20,'Illegal planet radius!');
  724. end;
  725. Until legal;
  726. PutImage(x,y,pointr.imagepointr^,XORPut); {kill the pointer}
  727. Inc(np); {actually add the new planet info}
  728. pl[p].d:=1.0; pl[p].GM:=G*2*pi*sqr(pl[p].r)*1.0; {initialize it}
  729. SetColor(color[1]); {draw it}
  730. Circle(pl[p].cx,pl[p].cy,pl[p].r);
  731. SetFillStyle(SolidFill,color[1]);
  732. FloodFill(pl[p].cx,pl[p].cy,color[1]);
  733. end;
  734. Procedure ChangePlanet; {change density [color] of a planet}
  735. var c : char; {will not change black holes}
  736. i,p,jump : integer;
  737. x,y,xold,yold,minr,t : longint;
  738. moveit,legal : boolean;
  739. begin
  740. ClearDialogBox;
  741. legal:=false;
  742. if np>0 then {see if any non-black holes exist}
  743. for i:=1 to np do
  744. if pl[i].r<>0 then legal:=true;
  745. if (np=0) or (not legal) then {sorry!}
  746. begin
  747. OutTextXY(0,0,'No planets to change!');
  748. delay(2000);
  749. exit;
  750. end;
  751. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  752. OutTextXY(0,10,'Enter to pick planet, + and - to change size of jumps.');
  753. jump:=30;
  754. x:=100; y:=100; PutImage(x,y,pointr.imagepointr^,XORPut);
  755. Repeat {repeat until RETURN or Esc}
  756. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  757. (c='+') or (c='-') or (c=Return) or (c=Esc);
  758. moveit:=false; xold:=x; yold:=y;
  759. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  760. if moveit then
  761. begin
  762. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  763. PutImage(x,y,pointr.imagepointr^,XORPut);
  764. moveit:=false;
  765. end;
  766. Until (c=Return) or (c=Esc);
  767. PutImage(x,y,pointr.imagepointr^,XORPut); {kill the pointer}
  768. if c=Esc then exit;
  769. p:=0; minr:=trunc(sqrt(sqr(screen.lx)+sqr(screen.ly)));
  770. for i:=1 to np do {find closest non-black hole planet}
  771. begin
  772. t:=trunc(sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy)));
  773. if (t<minr) and (pl[i].r<>0) then begin minr:=t; p:=i; end;
  774. end;
  775. ClearDialogBox;
  776. OutTextXY(0, 0,'Change to: 1. Red 2. Green 3. Blue Esc aborts');
  777. OutTextXY(0,10,'Option: '); {get a density}
  778. Repeat c:=ReadKey; Until (c='1') or (c='2') or (c='3') or (c=Esc);
  779. if c=Esc then exit;
  780. i:=Ord(c)-48;
  781. pl[p].d:=(i+1)/2.0; {new density}
  782. SetColor(color[i]); {redraw}
  783. Circle(pl[p].cx,pl[p].cy,pl[p].r);
  784. SetFillStyle(SolidFill,color[i]);
  785. FloodFill(pl[p].cx,pl[p].cy,color[i]);
  786. end;
  787. Procedure DeletePlanet; {kill a planet/black hole}
  788. var c : char;
  789. i,p,jump : integer;
  790. x,y,xold,yold,minr,t : longint;
  791. moveit : boolean;
  792. begin
  793. ClearDialogBox;
  794. if np=0 then {nobody there!}
  795. begin
  796. OutTextXY(0,0,'No planets to delete!');
  797. delay(2000);
  798. exit;
  799. end;
  800. OutTextXY(0, 0,'Use cursors to move pointer. (Num Lock on) Esc aborts');
  801. OutTextXY(0,10,'Enter to pick planet, + and - to change size of jumps.');
  802. jump:=30;
  803. x:=100; y:=100; PutImage(x,y,pointr.imagepointr^,XORPut);
  804. Repeat
  805. Repeat c:=ReadKey; Until (c='4') or (c='8') or (c='6') or (c='2') or
  806. (c='+') or (c='-') or (c=Return) or (c=Esc);
  807. moveit:=false; xold:=x; yold:=y;
  808. InterpKey(c,x,y,pointr.coffx,pointr.coffy,pointr.r,jump,moveit);
  809. if moveit then
  810. begin
  811. PutImage(xold,yold,pointr.imagepointr^,XORPut);
  812. PutImage(x,y,pointr.imagepointr^,XORPut);
  813. moveit:=false;
  814. end;
  815. Until (c=Return) or (c=Esc);
  816. PutImage(x,y,pointr.imagepointr^,XORPut);
  817. if c=Esc then exit;
  818. p:=0; minr:=trunc(sqrt(sqr(screen.lx)+sqr(screen.ly)));
  819. for i:=1 to np do {find the closest planet/black hole}
  820. begin
  821. t:=trunc(sqrt(sqr(x-pl[i].cx)+sqr(y-pl[i].cy)));
  822. if t<minr then begin minr:=t; p:=i; end;
  823. end;
  824. if p<9 then {move everybody above the one deleted one down}
  825. for i:=p to np-1 do
  826. pl[i]:=pl[i+1];
  827. Dec(np); {delete}
  828. DrawSetup; {redraw}
  829. end;
  830. Procedure Changes; {changes menu}
  831. var option : char;
  832. begin
  833. Repeat
  834. ClearDialogBox;
  835. SetColor(LightGray);
  836. OutTextXY(0, 0,'1. Move ship 2. Move planet 3. Make planet');
  837. OutTextXY(0,10,'4. Change planet 5. Delete planet Esc quits menu');
  838. OutTextXY(0,20,'Option: ');
  839. option:=ReadKey;
  840. Case option of
  841. '1' : MoveShip;
  842. '2' : MovePlanet;
  843. '3' : MakePlanet;
  844. '4' : ChangePlanet;
  845. '5' : DeletePlanet;
  846. end;
  847. Until option=Esc;
  848. end;
  849. Procedure MainMenu; {main menu}
  850. var option : char;
  851. begin
  852. Repeat
  853. ClearDialogBox;
  854. SetColor(LightGray);
  855. OutTextXY(0,0,'1. Playing the game 2. Options 3. Changes 4. Quit');
  856. OutTextXY(0,10,'Option: ');
  857. option:=ReadKey;
  858. Case option of
  859. '1' : PlayingtheGame;
  860. '2' : Options;
  861. '3' : Changes;
  862. end;
  863. Until option='4';
  864. end;
  865. Procedure Title; {title screen and credits}
  866. begin
  867. SetTextStyle(SansSerifFont,HorizDir,9);
  868. OutTextXY(25,100,'Gravity Wars');
  869. SetTextStyle(SansSerifFont,HorizDir,2);
  870. OutTextXY(300,300,'by Sohrab Ismail-Beigi');
  871. delay(3000);
  872. SetTextStyle(DefaultFont,HorizDir,0);
  873. end;
  874. BEGIN
  875. Init;
  876. Title;
  877. RandomSetup;
  878. DrawSetup;
  879. MainMenu;
  880. Finish;
  881. END.
  882. $Log$
  883. Revision 1.2 2000-07-13 11:33:08 michael
  884. + removed logs
  885. }