' File: car2.lst
'
' Car racing game
' ===============
'
'
GOSUB init  !Define the game parameters
GOSUB drive !let's go
'
'
DEFWRD "a-z"
' Procedures:
'  init()
'     Defining the global game parameters
'  drive()
'     Plot course of next road section and get it done
'  road()
'     Start the individual phases in the generation
'     of a new road section
'  difficult()
'     Setting new game parameters (Road width, obstacle
'     frequency, speed)
'  build()
'     Build (draw) a new road section
'  contraflow()
'     Manage traffic from opposite direction
'
PROCEDURE init
  ass$=SPACE$(500)  ! include assembler program
  ass%=VARPTR(ass$)
  BLOAD "car.sup",ass%
  '
  ' Set start parameters
  '
  maxspeed=10
  narrow=1    ! steps in narrowing road
  degree=0    ! starting probability of contraflow traffic
  obstweight=100    ! The larger the value, the
  ' lower the probability of
  ' obstacles
  obstwidth=8    ! Obstacle width
  obstlength=8      ! Obstacle length
  obstcount=-1   ! no obstacles as yet
  speed=1        ! Speed in pixels
  distance=0     ! Distance covered in pixels
  left=170       ! Starting position of road
  right=470
  pos=310
  '
  DEFFILL 1,1,-1 ! Prepare road
  GRAPHMODE 1
  PBOX left,0,right,399
  VOID C:ass%(pos)
RETURN
'
PROCEDURE drive
  DO
    deltay=RND(1)*800    ! calculate new road
    ' position
    deltax=(638-right+left)*RND(1)-left+1  ! IF avoids excessively
    ' sharp curves
    IF ABS(deltax)*640*speed/(maxspeed*(right-left))>deltay
      deltax=0
      deltay=10*RND(1)
    ENDIF
    ADD deltay,20
    '
    base=left                        ! Draw straight line through
    IF RND(1)<0.5                    ! the new finishing point,
      FOR y=0 TO deltay STEP speed  ! starting from base position.
        leftnew=base+deltax*SIN(y/deltay*PI/2) ! Round off by
        rightnew=right+leftnew-left         !multiplication with
        ' COS or SIN for nicer curve
        GOSUB road
        ADD distance,speed
      NEXT y
    ELSE
      FOR y=0 TO deltay STEP speed
        leftnew=base+deltax*(1-COS(y/deltay*PI/2))
        rightnew=right+leftnew-left
        GOSUB road
        ADD distance,speed
      NEXT y
    ENDIF
  LOOP
RETURN
'
PROCEDURE road
  IF C:ass%(speed)<>0      !scroll
    PRINT CHR$(7);
  ENDIF
  GOSUB difficult         ! new difficulty level
  GOSUB build             ! draw street
  GOSUB contraflow        ! calc. contraflow
RETURN
'
PROCEDURE difficult
  ' Set new games parameters:
  '  narrowing: number of pixels to be cut off on left and right
  '  This variable is shared with the procedure "build"
  '  speed: new scrolling speed
  '  degree: probability of a new obstacle
  narrowing=0
  IF (distance AND 63)=0
    IF speed<maxspeed AND speed*RND(1)<2*maxspeed
      INC speed
    ENDIF
    IF (right-left-narrow-narrow)*RND(1)>3*obstwidth
      narrowing=narrow
    ELSE
      degree=degree+(16-degree)*(RND(1)-0.2)
    ENDIF
    IF RND(1)<0.2 AND speed+speed>maxspeed
      SUB speed,2
    ENDIF
    IF RND(1)*degree>4 AND right-left<8*obstwidth
      narrowing=-narrow-narrow
    ENDIF
    IF (right-left)<RND(1)*20*obstwidth
      degree=degree*RND(1)
    ENDIF
  ENDIF
RETURN
'
PROCEDURE build
  ADD base,narrowing      !Correct base, left and right border in the
  ADD leftnew,narrowing   !event of a narrowing.
  SUB rightnew,narrowing
  IF leftnew<>left        !If left border has moved, update screen
    IF leftnew<left
      DEFFILL 1,1,-1       !accordingly (erase or add road section
      PBOX leftnew,399-speed,left,399 !on the left)
    ELSE
      DEFFILL 0,1,-1
      PBOX left,399-speed,leftnew-1,399
    ENDIF
  ENDIF
  IF rightnew<>right      !As for the left border, but now
    ' for the right
    IF rightnew>right
      DEFFILL 1,1,-1
      PBOX right,399-speed,rightnew,399
    ELSE
      DEFFILL 0,1,-1
      PBOX rightnew+1,399-speed,right,399
    ENDIF
  ENDIF
  right=rightnew          !note new right and left borders
  left=leftnew
RETURN
'
PROCEDURE contraflow
  IF RND(1)*obstweight<=degree AND obstcnt<0   !If no
    ' obstacle is
    obstpos=left+RND(1)*(right-left-obstwidth)   !being drawn,
    ' perhaps
    obstcnt=obstlength                           !call for a
    ' new one
  ELSE
    IF obstcnt>=0                                !If obstacle
      ' on the way,
      IF obstpos<left                           !keep it on
        obstpos=left                           !on the road
      ENDIF
      IF obstpos+obstwidth>=right
        obstpos=right-obstwidth
      ENDIF
    ENDIF
  ENDIF
  '
  IF obstcnt>=0           !If there is an obstacle to manage,
    IF obstcnt>speed     !draw the part just coming into view
      DEFFILL 0,1,-1
      PBOX obstpos,399-speed,obstpos+obstwidth,399
      SUB obstcnt,speed
    ELSE
      IF obstcnt>0      !If speed > rest of obstacle, draw
        ' rest of obstacle and counter = 0
        DEFFILL 0,1,-1
        PBOX obstpos,399-speed,obstpos+obstwidth,399-speed+obstcnt
        obstcnt=0
      ELSE
        DEFFILL 1,1,-1    !If counter=0, draw obstacle end
        PBOX obstpos,399-speed,obstpos+obstwidth,399
        obstcnt=-1        !and mark obstacle as finished
      ENDIF
    ENDIF
  ENDIF
RETURN
