`The number of checkpoints in the race
checkpoints=26
 
gosub setupgame
`___________________________________________________________________________________
 
do
   if endgame=0
      if endgame=0 then Elapsed#=(Timer()-T#)/1000
      if waypoint#>ai_waypoint# then pos$="1st"
      if waypoint#=ai_waypoint# and root#<ai_root# then pos$="1st"
      if waypoint#=ai_waypoint# and root#>ai_root# then pos$="2nd"
      if waypoint#<ai_waypoint# then pos$="2nd"
 
      Text 10,10,pos$
      Text 10,60,Str$(waypoint#-2)+"/"+Str$(checkpoints-2)
   endif
 
   if endgame=0
      if upkey()=1 and speed#=>0 then speed#=speed#+0.02
      if upkey()=1 and speed#<0 then speed#=speed#+0.05
      if downkey()=1 and speed#>-1 then speed#=speed#-0.05
      if downkey()=0 and upkey()=0 then speed#=speed#/1.02
   endif
   if endgame=1 and speed#>0 then speed#=speed#-0.05
 
   if rightkey()=1 and steer#<2.5 then steer#=steer#+0.1
   if leftkey()=1 and steer#>-2.5 then steer#=steer#-0.1
   if rightkey()=0 and leftkey()=0 then steer#=steer#/1.2
   if speed#>0 then angleY#=angleY#+steer#
   if speed#<0 then angleY#=angleY#-steer#
 
   if endgame=0
      gosub collision
      gosub ai_collision
   endif
`___________________________________________________________________________________
 
   rotate object 1,0,wrapvalue(angleY#),wrapvalue(0-angleZ#)
   X#=newXvalue(X#,angleY#,speed#)
   Z#=newZvalue(Z#,angleY#,speed#)
   if X#>200 then X#=200:speed#=speed#/1.02
   if X#<0 then X#=0:speed#=speed#/1.02
   if Z#>200 then Z#=200:speed#=speed#/1.02
   if Z#<0 then Z#=0:speed#=speed#/1.02
   Position object 1,X#,0,Z#
 
   cam_angleY#=cam_angleY#+(angleY#-cam_angleY#)/10
   angleZ#=angleZ#+(AngleY#-angleZ#)/10
   camX#=newXvalue(object position x(1),cam_angleY#+180,speed#+20)
   camZ#=newZvalue(object position z(1),cam_angleY#+180,speed#+20)
   position camera camX#,speed#+10,camZ#
   point camera object position x(1),1,object position z(1)
 
   fov#=speed#/5
   set camera fov fov#+1
 
   root#=sqrt((((object position X(waypoint#)-X#)/2)^2)+(((object position Z(waypoint#)-Z#)/2)^2))
`___________________________________________________________________________________
 
   ai_ang#=wrapvalue(atanfull(ai_X#-object position X(ai_waypoint#),ai_Z#-object position Z(ai_waypoint#))-ai_angleY#)
 
   if wrapvalue(ai_ang#-ai_steer#)<180 then ai_behaviour=2
   if wrapvalue(ai_ang#-ai_steer#)>180 then ai_behaviour=1
   if wrapvalue(ai_ang#-ai_steer#)=180 then ai_behaviour=0
 
   ai_root#=sqrt((((object position X(ai_waypoint#)-ai_X#)/2)^2)+(((object position Z(ai_waypoint#)-ai_Z#)/2)^2))
 
   if ai_speed#*2<ai_root#/10 then ai_speed#=ai_speed#+0.02 else ai_speed#=ai_speed#/1.02
   if ai_behaviour=1 and ai_steer#<2.5 then ai_steer#=ai_steer#+0.5
   if ai_behaviour=2 and ai_steer#>-2.5 then ai_steer#=ai_steer#-0.5
   if ai_behaviour<>1 and ai_behaviour<>2 then ai_steer#=ai_steer#/1.2
   if ai_speed#>0 then ai_angleY#=ai_angleY#+ai_steer#
   if ai_speed#<0 then ai_angleY#=ai_angleY#-ai_steer#
 
   rotate object 2,0,wrapvalue(ai_angleY#),wrapvalue(0-ai_angleZ#)
   ai_X#=newXvalue(ai_X#,ai_angleY#,ai_speed#)
   ai_Z#=newZvalue(ai_Z#,ai_angleY#,ai_speed#)
   if ai_X#>200 then ai_X#=200:ai_speed#=ai_speed#/1.02
   if ai_X#<0 then ai_X#=0:ai_speed#=ai_speed#/1.02
   if ai_Z#>200 then ai_Z#=200:ai_speed#=ai_speed#/1.02
   if ai_Z#<0 then ai_Z#=0:ai_speed#=ai_speed#/1.02
   Position object 2,ai_X#,0,ai_Z#
   ai_angleZ#=ai_angleZ#+(ai_AngleY#-ai_angleZ#)/10
 
   if endgame=1 and speed#<0 then gosub finnish
   if endgame=0 then gosub update_map
loop
`___________________________________________________________________________________
 
setupgame:
   checkpoints=checkpoints+2
   waypoint#=3
   ai_waypoint#=3
   set display mode 1280,1024,32
   sync on:sync rate 30
   hide mouse
   randomize timer()
 
   make matrix 1,200,200,10,10
   position matrix 1,0,-2,0
 
   make object cube 1,4
   make object cube 2,4
 
   color object 1,RGB(55,55,55)
   color object 2,RGB(20,20,20)
 
   create bitmap 1,200,200
   set current bitmap 1
   get image 1,0,0,200,200
   set current bitmap 0
   ink rgb(255,255,255),0
 
   make object plain 32,200,200
   lock object on 32
   position object 32,-490,-320,800
   ghost object on 32
   texture object 32,1
 
   for t=3 to checkpoints
   make object cube t,4
   position object t,rnd(200),0,rnd(200)
   next t
   color object 3,RGB(225,0,0)
 
   T#=Timer()
   set text font "Berlin Sans FB"
   set text size 50
return
 
collision:
   if object collision(1,waypoint#)=1
      hide object waypoint#
      if waypoint#=checkpoints
         message$="FINISH!!"
         endgame=1
         return
         `gosub finnish
      endif
      color object waypoint#+1,RGB(225,0,0)
      waypoint#=waypoint#+1
   endif
return
 
ai_collision:
   if object collision(2,ai_waypoint#)=1
      ghost object on ai_waypoint#
      if ai_waypoint#=checkpoints
         message$="YOU LOZE!!"
         endgame=1
         return
         `gosub finnish
      endif
      ai_waypoint#=ai_waypoint#+1
   endif
return
 
update_map:
   set current bitmap 1
   ink rgb(0,100,0),rgb(0,100,0)
   cls
 
   `the player cube (yellow, 2x as big)
   ink rgb(255,255,0),0
   box X#-2,Z#-2,X#+2,Z#+2
 
   `the ai cube (black)
   ink 0,0
   box ai_X#-1,ai_Z#-1,ai_X#+1,ai_Z#+1
   ink rgb(255,255,255),0
 
   `the waypoint cubes (white)
   for t=waypoint# to checkpoints
      box object position X(t)-1,object position Z(t)-1,object position X(t)+1,object position Z(t)+1
   next t
 
   `the destination waypoint cube (red, 2x as big)
   ink rgb(255,0,0),0
   box object position X(waypoint#)-2,object position Z(waypoint#)-2,object position X(waypoint#)+2,object position Z(waypoint#)+2
   flip bitmap 1
 
   get image 1,0,0,200,200
   set current bitmap 0
   ink rgb(255,255,255),0
   texture object 32,1
 
   zrotate object 32,object angle y(1)
return
 
finnish:
   if Elapsed#>60 then Elapsed#=Elapsed#-60:min=min+1:goto finnish
   repeat
      cls rgb(225,30,30)
 
      a=rnd(5)
      if a=0 then ink rgb(225,30,30),0 else ink rgb(0,0,0),0
      set text font "impact"
      set text size 100
      center text screen width()/2,screen height()/2-100,message$
 
      ink rgb(0,0,0),0
      set text font "Courier"
      set text size 15
      if min>0
         center text screen width()/2,screen height()/2-10,"In just "+Str$(min)+" minute(s) and "+Str$(int(Elapsed#))+" seconds"
      else
         center text screen width()/2,screen height()/2-10,"In just "+Str$(int(Elapsed#))+" seconds"
      endif
 
      sync
   until world_domination=1
 
 
remstart
   this is the part where I explain what all the varaibles are
 
   ai_behaviour      = used for the ai steering behaviour; 0=no steeing 1=right 2=left
   checkpoints       = the total number of checkpoints
   endgame           = if 1 then the game has ended
   min               = number of minutes the player used to get all the checkpoints; used only in the finnish subroutine
   t                 = used for displaying white dots on the map; used only in the update_map subroutine
   world_domination  = used at the end of the game; to make the end message flikker on and off
 
   ai_ang#           = if 0 then the ai player is facing directly to the current ai checkpoint
   ai_angleY#        = the angle of the ai player; viewed from above
   ai_angleZ#        = the angle of the ai player; viewed from the back
   ai_root#          = the distance between the ai and the current active checkpoint for the ai
   ai_speed#         = the speed of the ai
   ai_steer#         = the steering angle for the ai
   ai_waypoint#      = the active checkpoint for the ai
   ai_X#             = the X position of the ai player
   ai_Z#             = the Z position of the ai player
   angleY#           = the angle of the player; viewed from above
   angleZ#           = the angle of the player; viewed from the back (where the camera sits)
   cam_angleY#       = the angle of the camera; viewed from above
   camX#             = the X position of the camera
   camZ#             = the Z position of the camera
   Elapsed#          = the time that has elapsed in the game
   fov#              = the field of vieuw for the camera
   root#             = the distance between the player and the current active checkpoint for the player
   speed#            = the speed of the player
   steer#            = the steering angle (the angle of the front wheels)
   T#                = the time at the beginning of the game
   waypoint#         = the current active (red) checkpoint for the player
   X#                = the X position of the player
   Z#                = the Z position of the player
 
   message$          = the end message
   pos$              = your position in the game