Basics of Oberon-07

Description of the page content

Conversion of old BASIC programs to Oberon-07 in order to learn the basics of this language.

Tags:

Chase

(*

Chase

Original version in BASIC:

  Anonymous. Published in 1977 in The Best of Creative Computing
  Volumen 2, page 253:

  https://www.atariarchives.org/bcc2/showpage.php?page=253

This version in Oberon-07:

  Copyright (c) 2022, 2023, Marcos Cruz (programandala.net)
  SPDX-License-Identifier: Fair

Last modified 20231215T1548+0100.

*)

MODULE chase;

IMPORT
  Input0,
  Out,
  obqChar,
  obqKey,
  obqRandom,
  obqScreen;

CONST

  (* Map size: *)
  xSize             = 20;
  lastX             = xSize-1;
  ySize             = 10;
  lastY             = ySize-1;

  (* Values of `theEnd` beside the default 0: *)
  quit              =  1;
  electrified       =  2;
  killed            =  3;
  victory           =  4;

  machines          =  5;
  lastMachine       = machines-1;
  machinesDrag      =  2; (* probability not moving: 0=0%, 1=50%, 2=66%, 3=75%, etc. *)

  (* Map content: *)
  empty             = " ";
  fence             = "X";
  machine           = "m";
  human             = "@";
  fences            =  15; (* inner obstacles, not the border *)

VAR

  map               : ARRAY ySize,xSize OF CHAR;

  machineX          : ARRAY machines OF INTEGER;
  machineY          : ARRAY machines OF INTEGER;
  operative         : ARRAY machines OF BOOLEAN;
  destroyedMachines : INTEGER; (* counter *)

  humanX            : INTEGER;
  humanY            : INTEGER;

  theEnd            : INTEGER;
  moving            : BOOLEAN;
  xInc              : INTEGER;
  yInc              : INTEGER;

PROCEDURE Instructions;
(*

  Display the game instructions and wait for a key.

*)
BEGIN

  obqScreen.Clear;
  Out.String("You (");
  Out.Char(human);
  Out.String(") are in a high voltage maze with ");
  Out.Int(machines,0);Out.Ln;
  Out.String("security machines (");
  Out.Char(machine); Out.String(") trying to kill you.");Out.Ln;
  Out.String("You must maneuver them into the maze (");
  Out.Char(fence);Out.Char(")");Out.Ln;
  Out.String("to survive.");Out.Ln;
  Out.Ln;
  Out.String("Good luck!");Out.Ln;
  Out.Ln;
  Out.String("The movement keys are the following 8 digits:");Out.Ln;
  Out.Ln;
  obqScreen.Tab(10);Out.String("  \   ^   / ");Out.Ln;
  obqScreen.Tab(10);Out.String("   \  |  /  ");Out.Ln;
  obqScreen.Tab(10);Out.String("    7 8 9   ");Out.Ln;
  obqScreen.Tab(10);Out.String(" <--4   6-->");Out.Ln;
  obqScreen.Tab(10);Out.String("    1 2 3   ");Out.Ln;
  obqScreen.Tab(10);Out.String("   /  |  \  ");Out.Ln;
  obqScreen.Tab(10);Out.String("  /   V   \ ");Out.Ln;

  Out.Ln;
  Out.String("Plus '0' to end the game.");Out.Ln;

  Out.Ln;
  Out.String("Press any key to start.");
  WHILE Input0.Available() = 0 DO
  END;

END Instructions;

PROCEDURE Yes(question: ARRAY OF CHAR): BOOLEAN;
(*

  Display the given string `question` followed by the valid answer
  keys and wait for a valid keypress ("Y" or "N", case-insensitive).
  If the key is "Y" return `TRUE`, otherwise return `FALSE`.

*)
VAR key: CHAR;
BEGIN
  Out.String(question);
  Out.String(" (Y/N)");
  Out.Ln;
  REPEAT
    key := obqChar.Upper(obqKey.Wait());
  UNTIL (key = "Y") OR (key = "N");
  RETURN key = "Y"
END Yes;

PROCEDURE PrintMap;
(*

  Display the map at the top left corner of the screen.

*)
VAR x,y: INTEGER;
BEGIN
  obqScreen.Home;
  FOR y := 0 TO lastY DO
    FOR x := 0 TO lastX DO
      Out.Char(map[y,x])
    END;
    Out.Ln;
  END;
END PrintMap;

PROCEDURE IsBorder(y,x: INTEGER): BOOLEAN;
(*

  If the given map coordinates `y` and `x` are part of the border map
  (i.e. its surrounding fence), return `TRUE`, otherwise return
  `FALSE`.

*)
BEGIN
  RETURN (y = 0) OR (x = 0) OR (y = lastY) OR (x = lastX)
END IsBorder;

PROCEDURE Place(VAR y,x: INTEGER; c: CHAR);
(*

  Place the given character `c` at a random empty position of the map
  and update the given variables `y` and `x` with that position.

*)
VAR tmpY,tmpX: INTEGER;
BEGIN
    REPEAT
      tmpY := obqRandom.IntRange(1,lastY-1);
      tmpX := obqRandom.IntRange(1,lastX-1);
    UNTIL map[tmpY,tmpX] = empty;
    y := tmpY;
    x := tmpX;
    map[y,x] := c
END Place;

PROCEDURE InhabitMap;
(*

  Occupy the map with the machines, the inner fences and the human.

*)
VAR n,x,y: INTEGER;
BEGIN

  FOR n := 0 TO lastMachine DO
    Place(machineY[n],machineX[n],machine);
    operative[n] := TRUE
  END;

  FOR n := 1 TO fences DO
    Place(y,x,fence); (* XXX TODO *)
  END;

  Place(humanY,humanX,human);

END InhabitMap;

PROCEDURE MakeMap;
(*

  Make an empty map with a surrounding fence.

*)
VAR x,y: INTEGER;
BEGIN

  FOR y := 0 TO lastY DO
    FOR x := 0 TO lastX DO
      IF IsBorder(y,x) THEN
        map[y,x] := fence
      ELSE
        map[y,x] := empty
      END;
    END;
  END;

END MakeMap;

PROCEDURE Init;
(*

  Init the game by making a new map and resetting the variables.

*)
BEGIN
  MakeMap;
  InhabitMap;
  destroyedMachines := 0;
  theEnd := 0;
END Init;

PROCEDURE MoveMachine(m: INTEGER);
(*

  Move the given machine `m`.

*)
VAR
  maybe: INTEGER;
BEGIN

  map[machineY[m],machineX[m]] := empty;

  maybe := obqRandom.IntRange(0,1);
  IF machineY[m]>humanY THEN
    DEC(machineY[m],maybe)
  ELSIF machineY[m]<humanY THEN
    INC(machineY[m],maybe)
  END;

  maybe := obqRandom.IntRange(0,1);
  IF (machineX[m]>humanX) THEN
    DEC(machineX[m],maybe)
  ELSIF (machineX[m]<humanX) THEN
    INC(machineX[m],maybe)
  END;

  IF map[machineY[m],machineX[m]] = empty THEN
    map[machineY[m],machineX[m]] := machine
  ELSIF map[machineY[m],machineX[m]] = fence THEN
    operative[m] := FALSE;
    INC(destroyedMachines);
    IF destroyedMachines = machines THEN
      theEnd := victory
    END
  ELSIF map[machineY[m],machineX[m]] = human THEN
    theEnd := killed
  END;

END MoveMachine;


PROCEDURE MoveMachines;
(*

  Move all of the operative machines.

*)
VAR machine: INTEGER;
BEGIN

  FOR machine := 0 TO lastMachine DO
    IF operative[machine] & (obqRandom.IntMax(machinesDrag) = 0) THEN
      MoveMachine(machine)
    END;
  END;

END MoveMachines;

PROCEDURE GetMove(VAR yInc,xInc: INTEGER): BOOLEAN;
(*

  Read a keypress and update the given variables `yInc` and `xInc`
  according to the direction, with values -1..1.

  If the key is "0", update the `theEnd`.

  Return `TRUE` if a movement key was pressed, otherwise `FALSE`.

*)
VAR key: CHAR;
BEGIN

  yInc := 0;
  xInc := 0;

  Input0.Read(key);
  CASE ORD(key) OF

    48: theEnd := quit            | (* "0" = quit *)

    49: yInc := +1; xInc := -1    | (* "1" = SW *)
    50: yInc := +1;               | (* "2" = S  *)
    51: yInc := +1; xInc := +1    | (* "3" = SE *)
    52:             xInc := -1    | (* "4" = W  *)
    54:             xInc := +1    | (* "6" = E  *)
    55: yInc := -1; xInc := -1    | (* "7" = NW *)
    56: yInc := -1;               | (* "8" = N  *)
    57: yInc := -1; xInc := +1    | (* "9" = NE *)

    0..47,53,58..255:               (* other = nothing *)

  END;

  RETURN (yInc # 0) OR (xInc # 0)
END GetMove;

BEGIN

obqRandom.Randomize;
obqScreen.Clear;
Out.String("CHASE");
Out.Ln;

IF Yes("Do you want instructions?") THEN
  Instructions;
END;

REPEAT (* game loop *)

  obqScreen.Clear;
  Init;

  REPEAT (* action loop *)

    PrintMap;
    moving := GetMove(yInc,xInc);

    IF theEnd = 0  THEN
      IF moving THEN
        map[humanY,humanX] := empty;
        IF map[humanY+yInc,humanX+xInc] = fence THEN
          theEnd := electrified
        ELSIF map[humanY+yInc,humanX+xInc] = machine THEN
          theEnd := killed
        ELSE
          map[humanY,humanX] := empty;
          humanY := humanY + yInc;
          humanX := humanX + xInc;
          map[humanY,humanX] := human;
          PrintMap;
          MoveMachines
        END;
      END;
    END;

  UNTIL theEnd # 0; (* action loop *)

  CASE theEnd OF
    quit:
      Out.String("Sorry to see you quit.")                       |
    electrified:
      Out.String("Zap! You touched the fence!")                  |
    killed:
      Out.String("You have been killed by a lucky machine.")     |
    victory:
      Out.String("You are lucky, you destroyed all machines.");
  END;
  Out.Ln;

UNTIL ~ Yes("Do you want to play again?"); (* game loop *)

Out.String("Hope you don't feel fenced in.");
Out.Ln;
Out.String("Try again sometime.");
Out.Ln;

END chase.

Sinewave

(*

Sine Wave

Original version in BASIC:
  Creative Computing (Morristown, New Jersey, USA), ca. 1980.

This version in Oberon-07:
  Copyright (c) 2022, 2023, Marcos Cruz (programandala.net)
  SPDX-License-Identifier: Fair

Last modified 2020231103T2153+0100.

*)

MODULE sinewave;

IMPORT
  In,
  Math,
  Out,
  obqKey,
  obqScreen;

VAR
  step:   INTEGER;
  key:    CHAR;
  angle:  REAL;
  word:   ARRAY 2,80 OF CHAR;

BEGIN

obqScreen.Clear;
Out.String("Sine Wave");
Out.Ln;
Out.Ln;
Out.String("Original version in BASIC:");
Out.Ln;
obqScreen.Tab(4);
Out.String("Creative computing (Morristown, New Jersey, USA), ca. 1980.");
Out.Ln;
Out.String("This version in Oberon:");
Out.Ln;
obqScreen.Tab(4);
Out.String("Copyright (c) 2022, 2023, Marcos Cruz (programandala.net)")
Out.Ln;
Out.String("SPDX-License-Identifier: Fair")
Out.Ln;
Out.Ln;
Out.String("Press any key to start the program.");
Out.Ln;

key := obqKey.Wait();

obqScreen.Clear;

Out.String("Enter the first word:  ");
Out.Ln;
In.Line(word[0]);
Out.String("Enter the second word: ");
Out.Ln;
In.Line(word[1]);

obqScreen.Clear;

step    := 0;
angle   := 0.0;

WHILE angle<40.0 DO
  obqScreen.Tab(FLOOR(26.0+25.0*Math.sin(angle)));
  Out.String(word[ORD(ODD(step))]);
  Out.Ln;
  INC(step);
  angle := angle+0.25;
END

END sinewave.

Related pages

Basics off
Metaproject about the "Basics of…" projects.
Basics of 8th
Conversion of old BASIC programs to 8th in order to learn the basics of this language.
Basics of Ada
Conversion of old BASIC programs to Ada in order to learn the basics of this language.
Basics of Arturo
Conversion of old BASIC programs to Arturo in order to learn the basics of this language.
Basics of C#
Conversion of old BASIC programs to C# in order to learn the basics of this language.
Basics of C3
Conversion of old BASIC programs to C3 in order to learn the basics of this language.
Basics of Chapel
Conversion of old BASIC programs to Chapel in order to learn the basics of this language.
Basics of Clojure
Conversion of old BASIC programs to Clojure in order to learn the basics of this language.
Basics of Crystal
Conversion of old BASIC programs to Crystal in order to learn the basics of this language.
Basics of D
Conversion of old BASIC programs to D in order to learn the basics of this language.
Basics of Elixir
Conversion of old BASIC programs to Elixir in order to learn the basics of this language.
Basics of F#
Conversion of old BASIC programs to F# in order to learn the basics of this language.
Basics of Factor
Conversion of old BASIC programs to Factor in order to learn the basics of this language.
Basics of FreeBASIC
Conversion of old BASIC programs to FreeBASIC in order to learn the basics of this language.
Basics of Gleam
Conversion of old BASIC programs to Gleam in order to learn the basics of this language.
Basics of Go
Conversion of old BASIC programs to Go in order to learn the basics of this language.
Basics of Hare
Conversion of old BASIC programs to Hare in order to learn the basics of this language.
Basics of Haxe
Conversion of old BASIC programs to Haxe in order to learn the basics of this language.
Basics of Icon
Conversion of old BASIC programs to Icon in order to learn the basics of this language.
Basics of Io
Conversion of old BASIC programs to Io in order to learn the basics of this language.
Basics of Janet
Conversion of old BASIC programs to Janet in order to learn the basics of this language.
Basics of Julia
Conversion of old BASIC programs to Julia in order to learn the basics of this language.
Basics of Kotlin
Conversion of old BASIC programs to Kotlin in order to learn the basics of this language.
Basics of Lobster
Conversion of old BASIC programs to Lobster in order to learn the basics of this language.
Basics of Lua
Conversion of old BASIC programs to Lua in order to learn the basics of this language.
Basics of Nature
Conversion of old BASIC programs to Nature in order to learn the basics of this language.
Basics of Neat
Conversion of old BASIC programs to Neat in order to learn the basics of this language.
Basics of Neko
Conversion of old BASIC programs to Neko in order to learn the basics of this language.
Basics of Nelua
Conversion of old BASIC programs to Nelua in order to learn the basics of this language.
Basics of Nim
Conversion of old BASIC programs to Nim in order to learn the basics of this language.
Basics of Nit
Conversion of old BASIC programs to Nit in order to learn the basics of this language.
Basics of OCaml
Conversion of old BASIC programs to OCaml in order to learn the basics of this language.
Basics of Odin
Conversion of old BASIC programs to Odin in order to learn the basics of this language.
Basics of Pike
Conversion of old BASIC programs to Pike in order to learn the basics of this language.
Basics of Pony
Conversion of old BASIC programs to Pony in order to learn the basics of this language.
Basics of Python
Conversion of old BASIC programs to Python in order to learn the basics of this language.
Basics of Racket
Conversion of old BASIC programs to Racket in order to learn the basics of this language.
Basics of Raku
Conversion of old BASIC programs to Raku in order to learn the basics of this language.
Basics of Retro
Conversion of old BASIC programs to Retro in order to learn the basics of this language.
Basics of Rexx
Conversion of old BASIC programs to Rexx in order to learn the basics of this language.
Basics of Ring
Conversion of old BASIC programs to Ring in order to learn the basics of this language.
Basics of Rust
Conversion of old BASIC programs to Rust in order to learn the basics of this language.
Basics of Scala
Conversion of old BASIC programs to Scala in order to learn the basics of this language.
Basics of Scheme
Conversion of old BASIC programs to Scheme in order to learn the basics of this language.
Basics of Styx
Conversion of old BASIC programs to Styx in order to learn the basics of this language.
Basics of Swift
Conversion of old BASIC programs to Swift in order to learn the basics of this language.
Basics of V
Conversion of old BASIC programs to V in order to learn the basics of this language.
Basics of Vala
Conversion of old BASIC programs to Vala in order to learn the basics of this language.
Basics of Zig
Conversion of old BASIC programs to Zig in order to learn the basics of this language.

External related links