set display mode 1024,768,32
sync on
backdrop on
sync rate 60
color backdrop rgb(128,128,255)
hide mouse
wall=0:offset=210:startx=10:startz=60:accel#=0.01:turnmax#=1.5:maxspeed#=0.1:start=0:laps_to_win=10:win=0:scol=192
dim col(5):dim bcol(5):dim cars#(5,3):dim laps(5,2)
total_cars=5
for x=0 to 5
  cars#(x,1)=0.0:cars#(x,2)=0.0:cars#(x,3)=maxspeed#
next x
gosub make_track
gosub make_lights
gosub make_cars
gosub laps_board
set global collision on
quit=0
starttime=timer()
while quit=0
  if start=2
    newtime=timer()-starttime
    dt#=newtime-oldtime
    oldtime=newtime
    uturn=0
    if leftkey()
      cars#(0,2)=cars#(0,2)-0.05
      if cars#(0,2)<-turnmax# then cars#(0,2)=-turnmax#
      uturn=1
    endif
    if rightkey()
      cars#(0,2)=cars#(0,2)+0.05
      if cars#(0,2)>turnmax# then cars#(0,2)=turnmax#
      uturn=1
    endif
    if upkey()
      cars#(0,1)=cars#(0,1)+accel#
      if cars#(0,1)>cars#(0,3)*dt# then cars#(0,1)=cars#(0,3)*dt#
    endif
    if downkey() then cars#(0,1)=cars#(0,1)-accel#
    for x=0 to total_cars
      if x>0
        turn=0
        if abs(object position x(car+x))+abs(object position z(car+x))<250.0
          this_offset=0
        else
          if object position x(car+x)<0.0
            this_offset=-offset
          else
            this_offset=offset
          endif
        endif
        car_angle=object angle y(car+x)
        if this_offset <> 0
          dist#=sqrt((object position x(car+x)-this_offset)^2+object position z(car+x)^2)
          if object position x(car+x)-this_offset<>0
            angle=atan((object position z(car+x))/(object position x(car+x)-this_offset))
          else
            angle=90
          endif
          if object position x(car+x)-this_offset<=0
            angle=angle+180
          else
            if object position z(car+x)<0 then angle=angle+360
          endif
          track_angle=90-angle
          if track_angle<0 then track_angle=track_angle+360
          if car_angle>330 and track_angle<30 then track_angle=track_angle+360
          if car_angle<30 and track_angle>330 then track_angle=track_angle-360
        else
          if laps(x,1)=0 or (laps(x,1)=1 and laps(x,2)=1)
            track_angle=315
          else
            track_angle=225
          endif
        endif
        turn=0
        if this_offset<0
          track_angle=track_angle-180
          if track_angle<0 then track_angle=track_angle+360
          if car_angle>330 and track_angle<30 then track_angle=track_angle+360
          if car_angle<30 and track_angle>330 then track_angle=track_angle-360
          if car_angle>track_angle then gosub turn_left
          if dist#>160+x and car_angle+15>track_angle then gosub turn_left
          if dist#<140-x and car_angle-15<track_angle then gosub turn_right
        endif
        if this_offset>0
          if car_angle<track_angle then gosub turn_right
          if dist#>160.0+x and car_angle-15<track_angle then gosub turn_right
          if dist#<140.0-x and car_angle+15>track_angle then gosub turn_left
        endif
        if this_offset=0
          if car_angle<track_angle then gosub turn_right
          if car_angle>track_angle then gosub turn_left
        endif
        for y=0 to total_cars
          if  y<>x
            dist#=sqrt((object position x(car+x)-object position x(car+y))^2+(object position z(car+x)-object position z(car+y))^2)
            if dist#<50.0
              dist2#=sqrt((object position x(car+x)+cos(object angle y(car+x))*dist#-object position x(car+y))^2+(object position z(car+x)-sin(object angle y(car+x))*dist#-object position z(car+y))^2)
              if dist2#<15.0
                dist=150-sqrt((object position x(car+x)-this_offset)^2+(object position z(car+x))^2)
                if dist=0 then dist=-1
                cars#(x,2)=cars#(x,2)+sgn(dist)*0.4
                if abs(cars#(x,2))>turnmax# then cars#(x,2)=turnmax#*sgn(cars#(x,2))
                y=5
              endif
            endif
          endif
        next y
        for y=2 to total_walls
          ds#=intersect object(y,object position x(car+x),0,object position z(car+x),object position x(car+x)+cos(object angle y(car+x)+30)*30,0,object position z(car+x)-sin(object angle y(car+x)+30)*30)
          if ds#>0.0 and ds#<15.0
            gosub turn_left
          endif
          ds#=intersect object(y,object position x(car+x),0,object position z(car+x),object position x(car+x)+cos(object angle y(car+x)-30)*30,0,object position z(car+x)-sin(object angle y(car+x)-30)*30)
          if ds#>0.0 and ds#<15.0
            gosub turn_right
          endif
        next y
        if turn=0 then cars#(x,2)=cars#(x,2)*0.5
        cars#(x,1)=cars#(x,1)+accel#
        if cars#(x,1)>cars#(x,3)*dt# then cars#(x,1)=cars#(x,3)*dt#
        if cars#(x,1)<0.0 then cars#(x,1)=cars#(x,1)*0.8
        lastx#=object position x(car+x)
        lastz#=object position z(car+x)
        yrotate object car+x,object angle y(car+x)+cars#(x,2)
        position object car+x,object position x(car+x)+cos(object angle y(car+x))*cars#(x,1),0,object position z(car+x)-sin(object angle y(car+x))*cars#(x,1)
        hit=object collision(car+x,0)
        if hit>0
          cars#(x,1)=-cars#(x,1)
          position object car+x,lastx#,0,lastz#
          this_offset=atan((object position z(hit)-object position z(car+x))/(object position x(hit)-object position x(car+x)))-object angle y(car+x)
          if this_offset=0 then this_offset=1
          cars#(x,2)=cars#(x,2)+sgn(this_offset)*0.2
          if abs(cars#(x,2))>turnmax# then cars#(x,2)=turnmax#*sgn(cars#(x,2))
        endif
        if object angle y(car+x)<0 then yrotate object car+x,object angle y(car+x)+360
        if object angle y(car+x)>360 then yrotate object car+x,object angle y(car+x)-360
      endif
      if object position x(car+x)>offset+100 then laps(x,1)=1
      if object position x(car+x)<-offset-100 then laps(x,2)=1
      if object position x(car+x)>60
        if laps(x,1)=1 and laps(x,2)=1
          inc laps(x,0):if laps(x,0)=laps_to_win then win=1
          laps(x,1)=0:laps(x,2)=0
        endif
      endif
      if win=1 then cars#(x,1)=0
    next x
    x=0
    if uturn=0 then cars#(0,2)=cars#(0,2)*0.5
    if cars#(0,1)<0.0 then cars#(0,1)=cars#(0,1)*0.9
    lastx#=object position x(car)
    lastz#=object position z(car)
    lasty#=object angle y(car)
    yrotate object car,object angle y(car)+cars#(0,2)
    position object car,lastx#+cos(lasty#)*cars#(0,1),0,lastz#-sin(object angle y(car))*cars#(0,1)
    if (object collision(car,0) >0)
      cars#(0,1)=-cars#(0,1)
      position object car,lastx#,0,lastz#
    endif
    if object position x(car)>offset+100 then laps(0,1)=1
    if object position x(car)<-offset-100 then laps(0,2)=1
  else
    if start=0
      for j=1 to 6
        ink rgb(128+j*10,128+j*10,128+j*10),0
        box 375+j,150+j,625-j,200-j
      next j
      inc scol
      if scol>250 then scol=192
      ink rgb(scol,scol,scol),0
      text 400,165,"Press SPACEBAR to start"
      if spacekey() then start=1
    else
      for j=1 to 6
        if light(j,1)<251 and light(j,2)<251 and light(j,3)<251
          light(j,1)=light(j,1)+4
          light(j,2)=light(j,2)+4
          light(j,3)=light(j,3)+4
          color object lights+j,rgb(light(j,1),light(j,2),light(j,3))
          j=6
        else
          if j=6 then start=2
        endif
      next j
    endif
  endif
  paste image 2,400,0
  ink 0,0
  for z=0 to 5
    set cursor 570-len(str$(laps(z,0)))*10,z*20+22
    print laps(z,0)
    sprite z+1,420+laps(z,0)*10+laps(z,1)*3+laps(z,2)*3,z*20+20,3
  next z
  paste image 4,435,600
  position camera 0,520,0
  point camera 0,0,0
  sync
endwhile
end
 
function sgn(x)
  v=0
  if x<0 then v=-1
  if x>0 then v=1
endfunction v
turn_right:
  cars#(x,2)=cars#(x,2)+0.1
  turn=1
  if cars#(x,2)>turnmax# then cars#(x,2)=turnmax#
return
turn_left:
  cars#(x,2)=cars#(x,2)-0.1
  turn=1
  if cars#(x,2) < -turnmax# then cars#(x,2)=-turnmax#
return
make_track:
  inc wall
  make object plain wall,100,20
  create bitmap 1,100,20
  ink rgb(255,255,255),0
  box 0,0,100,20
  ink 0,0
  for x=0 to 80 step 20
    box x,0,x+10,10
    box x+10,10,x+20,20
  next x
  get image 1,0,0,100,20
  delete bitmap 1
  set current bitmap 0
  texture object wall,1
  rotate object wall,90,45,0
  position object wall,50,-10,50
 
  width_out=35
  width_in=18
  for angle=-135 to 135 step 10
    inc wall
    xpos#=cos(angle)*200
    zpos#=sin(angle)*200
    make object box wall,width_out,10,1
    position object wall,xpos#+offset,0,zpos#
    yrotate object wall,90-angle
    inc wall
    xpos#=cos(angle+180)*200
    zpos#=sin(angle+180)*200
    make object box wall,width_out,10,1
    position object wall,xpos#-offset,0,zpos#
    yrotate object wall,90-angle
    inc wall
    xpos#=cos(angle)*100
    zpos#=sin(angle)*100
    make object box wall,width_in,10,1
    position object wall,xpos#+offset,0,zpos#
    yrotate object wall,90-angle
    inc wall
    xpos#=cos(angle+180)*100
    zpos#=sin(angle+180)*100
    make object box wall,width_in,10,1
    position object wall,xpos#-offset,0,zpos#
    yrotate object wall,90-angle
  next angle
  inc wall
  make object box wall,93,10,1
  position object wall,-100,0,-32
  yrotate object wall,-45
  inc wall
  make object box wall,93,10,1
  position object wall,-100,0,32
  yrotate object wall,45
  inc wall
  make object box wall,93,10,1
  position object wall,100,0,-32
  yrotate object wall,45
  inc wall
  make object box wall,93,10,1
  position object wall,100,0,32
  yrotate object wall,-45
  inc wall
  make object box wall,80,10,1
  position object wall,-28,0,-101
  yrotate object wall,-45
  inc wall
  make object box wall,80,10,1
  position object wall,28,0,-101
  yrotate object wall,45
  inc wall
  make object box wall,80,10,1
  position object wall,-28,0,101
  yrotate object wall,45
  inc wall
  make object box wall,80,10,1
  position object wall,28,0,101
  yrotate object wall,-45
  total_walls=wall
return
 
make_cars:
car=wall+1
make object box car,10,1,5
make object cylinder car+1,3
xrotate object car+1,90.0
make mesh from object 1,car+1
delete object car+1
add limb car,1,1
offset limb car,1,3,0,2
add limb car,2,1
offset limb car,2,-4,0,3
add limb car,3,1
offset limb car,3,3,0,-2
add limb car,4,1
offset limb car,4,-4,0,-3
clone object car+1,car
clone object car+2,car
clone object car+3,car
clone object car+4,car
clone object car+5,car
col(0)=rgb(0,0,255)
col(1)=rgb(0,255,255)
col(2)=rgb(0,255,0)
col(3)=rgb(255,255,0)
col(4)=rgb(255,0,255)
col(5)=rgb(255,0,0)
bcol(0)=rgb(0,0,192)
bcol(1)=rgb(0,192,192)
bcol(2)=rgb(0,192,0)
bcol(3)=rgb(192,192,0)
bcol(4)=rgb(192,0,192)
bcol(5)=rgb(192,0,0)
for x=0 to 5
  color object car+x,col(x)
  color limb car+x,1,0:color limb car+x,2,0:color limb car+x,3,0:color limb car+x,4,0
  position object car+x,startx+x*10,0,startz-x*10
  yrotate object car+x,315
next x
return
 
make_lights:
  lights=wall
  dim light(6,3)
  data 128,0,0,128,128,64,128,128,64,128,128,64,128,128,64,0,128,0
  for j=1 to 6
    read light(j,1):read light(j,2):read light(j,3)
    make object sphere wall+j,15
    position object wall+j,70,0,200+(6-j)*20
    color object wall+j,rgb(light(j,1),light(j,2),light(j,3))
  next j
  wall=wall+6
return
 
laps_board:
  create bitmap 2,190,150
  ink rgb(0,128,0),0:box 0,0,190,150
  ink 0,0:box 10,20,180,140
  ink rgb(255,255,255),0
  set text font "arial":set text to bold:set text size 20
  text 70,0,"LAPS"
  for x=0 to 5
    ink bcol(x),0:box 20,x*20+21,145,x*20+39
    ink col(x),0:box 150,x*20+21,170,x*20+39
  next x
  get image 2,0,0,190,150
  delete bitmap 2
  create bitmap 3,20,20
  ink 0,0:box 0,0,20,20
  ink rgb(5,5,5),0
  for r=1 to 3
    circle 5,15,r:circle 15,15,r
  next r
  line 3,15,3,5:line 3,5,15,10:line 15,10,18,15:line 18,15,3,15
  get image 3,0,0,20,20
  delete bitmap 3
  create bitmap 3,150,150
  ink rgb(32,32,128),0:box 0,0,150,150
  ink rgb(128,128,255),0
  set text font "arial":set text size 20:set text to bold
  text 40,20,"BLUE CAR"
  set text size 14:ink rgb(128,255,128),0
  text 10,5,"First car to "+str$(laps_to_win)+" laps wins"
  set text size 12:set text to normal
  ink rgb(255,255,255),0
  line 10,75,40,75:line 10,75,20,65:line 10,75,20,85
  text 10,85,"turn left"
  line 110,75,140,75:line 140,75,130,65:line 140,75,130,85
  text 110,85,"turn right"
  line 75,40,75,70:line 75,40,65,50:line 75,40,85,50
  text 85,50,"speed":text 85,60,"up"
  line 75,110,75,140:line 75,140,65,130:line 75,140,85,130
  text 45,110,"slow":text 45,120,"down"
  get image 4,0,0,150,150
  delete bitmap 3
  set current bitmap 0
  set text size 20:set text to bold
return