
(***************************************************************
*
*		STARS---game
*
*  Donated by Ray Penley, June 1980
*
****************************************************************)


PROGRAM SHOOTINGSTARS;
(*
**  PROGRAM TITLE:	SHOOTING STARS
**
**  WRITTEN BY:		MARK J. BORGERSON
**  DATE WRITTEN:	JUL 1976
**
**  WRITTEN FOR:	PERSONAL ENJOYMENT
**
**  TRANSLATED:		Translated from BASIC
**			 by Ray Penley, SEPT 1979
**			16 April 80 - added KEYIN.
**
*)

TYPE
  VECTOR = ARRAY[1..9] OF INTEGER;
Var
  seed1, seed2:	INTEGER;
  stars, F5:	VECTOR;
  C:		INTEGER;

Procedure KEYIN(VAR CIX : char); EXTERNAL;

Procedure INSTRUCTIONS;
Var
  I : INTEGER;
BEGIN
Writeln;
Writeln('If you like brain teasers then you''re in for some fun.');
Writeln('The object of this puzzle is to solve a 3 X 3 matrix such that');
Writeln('*''s appeas in all positions except in the center which will be');
Writeln('''. The positions on the matrix board are referred to by ROWS');
Writeln('then COLUMNS. The upper right hand position would be referred');
Writeln('to as; 1,3.');
Writeln('When a * is made a '', its immediate neighbors change state,');
Writeln('then is: *''s become '' and vice versa.');
Writeln('In addition, changing corner positions also changes the center');
Writeln('position; changing center position also changes outside');
Writeln('middle positions. Have FUN!');
Writeln;
	(* TIMING LOOP *)
  For I:=1 to 5000 do ;
END(*---of INSTRUCTIONS---*);

Procedure SKIP(LINES:INTEGER);
Var
  I : INTEGER;
BEGIN
  FOR I := 1 TO LINES DO Writeln
END(*---of SKIP---*);

Procedure HEADING;
Var
  A : INTEGER;
BEGIN
  Writeln(' ':20, '***  SHOOTING STARS  ***');
  SKIP(2);
  Writeln('DO YOU WANT INSTRUCTIONS (YES=1 NO=0)');
  READ(A);
  IF A=1 THEN INSTRUCTIONS
END(*---of HEADING---*);

Procedure CLEAR;
(*	!!!  DEVICE DEPENDENT ROUTINE !!!	*)
BEGIN
  Write( CHR(26) )
END(*---of CLEAR---*);

Procedure HOMEUP;
(*	!!!  DEVICE DEPENDENT ROUTINE !!!	*)
BEGIN
  Write( CHR(30) )
END(*---of HOMEUP---*);

(*=================================================*
   Implement a Fibonacci series Random number generator.
   Written for PASCAL/Z By Raymond E. Penley, September 1979
   Add these lines to your program

Var  seed1, seed2 : INTEGER;

	Within the body of the main program but
	BEFORE calling RANDOM:
   SEEDRAND;
*=================================================*)

Procedure SEEDRAND;
(* INITIAL VALUES FOR seed1 AND seed2 MAY BE
   INPUT HERE  *)
BEGIN
   seed1 := 10946;
   seed2 := 17711
END;

FUNCTION RANDOM : INTEGER;
(**
   RANDOM will return numbers from 0 to 32767.
   Call RANDOM using the following convention:
	 Range		 Use
	  0 - 32	RANDOM DIV 1000
	  0 - 327	RANDOM DIV 100
          0 - 32767	RANDOM

GLOBAL
   seed1, seed2 : INTEGER
**)
CONST
  HALFINT = 16383; (* 1/2 OF MAXINT *)
Var
  HALF1, HALF2, HALFADD : INTEGER;

BEGIN
  HALF1 := seed1 DIV 2;
  HALF2 := seed2 DIV 2;
  IF (HALF1+HALF2) >= HALFINT THEN
    HALFADD := HALF1 + HALF2 - HALFINT
  ELSE
    HALFADD := HALF1 + HALF2;
  seed1 := seed2;
  seed2 := HALFADD * 2;(* Restore from previous DIVision *)
  RANDOM := seed2
END(*---of RANDOM---*);

Procedure INITIALIZE;
BEGIN
  CLEAR;
  C := 0;  (* SHOT COUNTER *)
  stars[1] := (-23);	F5[1] := 1518;
  stars[2] := (-3);	F5[2] := 1311;
  stars[3] := (-19);	F5[3] := 570;
  stars[4] := (-11);	F5[4] := 3289;
  stars[5] :=    2;	F5[5] := 2310;
  stars[6] := (-5);	F5[6] := 1615;
  stars[7] := (-13);	F5[7] := 2002;
  stars[8] := (-7);	F5[8] := 1547;
  stars[9] := (-17);	F5[9] := 1190;
END(*---of INITIALIZE---*);

Procedure LOAD;
Var
  I, X7 : INTEGER;
BEGIN
  FOR I := 1  TO 9 DO
    BEGIN
    X7 := ( RANDOM DIV 100 );
    IF X7 > 200 THEN stars[I] := (-stars[I]);
    END  (*FOR*)
END(*---of LOAD---*);

Procedure BOARD;
Var
  J : INTEGER;
BEGIN
  HOMEUP;
  WRITE(' ':20);
  FOR J := 1 TO 9 DO
    BEGIN
      IF stars[ J ] < 0 THEN WRITE( '''        ');
      IF stars[ J ] > 0 THEN WRITE( '*        ');
      IF J MOD 3 = 0 THEN
  	BEGIN
	  SKIP(3);
	  WRITE(' ':20)
	END(*IF*)
    END(*FOR*);
  Writeln
END(*---of BOARD---*);

Procedure PLAYTHEGAME;
Var
  D, X	    : INTEGER;
  ENDOFGAME : BOOLEAN;

	FUNCTION CHECK : INTEGER;
	(*
	 Check to if the F value for the shot can be evenly
	 divided by the stars value for each position. If the
	 stars value divides into F without a remainder, the
	 STAR or black hole is inverted (its sign is changed).
	GLOBAL
	  X	:INTEGER;
	  stars, F5 :VECTOR   *)
	Var
	  B1, K, Z5 :INTEGER;
	BEGIN
	  B1 := 0;
	  FOR K := 1 TO 9 DO
	    BEGIN
	      Z5 := ( F5[ X ] DIV stars[ K ] ) * stars[ K ];
	      IF Z5 = F5[ X ] THEN stars[ K ] := (-stars[ K ])
	    END; (*FOR*)
	  FOR K := 1 TO 9 DO
		B1 := B1 +stars[ K ];
	  CHECK := B1
	END(*---of CHECK---*);

	Procedure INPUT;
	(*
	GLOBAL
	  C, X :INTEGER
	  stars   :VECTOR	*)
	Var
	  CIX : Char;
	  ERROR : BOOLEAN;
	BEGIN
	  REPEAT
	    ERROR := FALSE;(*Turn ERROR flag off for REPEAT *)
	    WRITE('Your Shot ');
	    KEYIN(CIX);
	    X := (ORD(CIX) -ORD('0'));
	    Writeln;
	    C := C +1;
	    IF (X<1) OR (X>9) THEN
	      ERROR := TRUE
	    ELSE
	      IF stars[ X ] <= 0 THEN
	        BEGIN
		  Writeln('You can only Shoot Stars');
		  ERROR := TRUE
		END(* else *)
	  UNTIL NOT ERROR;
	  Writeln
	END(*---of INPUT---*);

BEGIN  (* PLAYTHEGAME *)
  ENDOFGAME := FALSE;
  REPEAT
    INPUT;
    D := CHECK;
    BOARD;
    IF D = (-100) THEN
      BEGIN
	Writeln('You lost!!!');
	ENDOFGAME := TRUE
      END
    ELSE
      IF D=96 THEN
	BEGIN
	  Writeln('You WIN!!!');
	  Writeln('You fired', C:3, ' shots');
	  ENDOFGAME := TRUE
	END
  UNTIL ENDOFGAME
END(*---of PLAYTHEGAME---*);

BEGIN (* MAIN PROGRAM *)
  HEADING;
  CLEAR;
  INITIALIZE;
  SEEDRAND; (* seed the Random Number Generator *)
  LOAD;
  BOARD;
  PLAYTHEGAME
END(*---of SHOOTING STARS---*).
