The source code is available as attached file.
It is also listed as following
[quote]
import java.awt.*;

public class traffic extends java.applet.Applet implements Runnable{
int yOffset=40;
TextField iField; //record time elapse
double time=0.0,ts=0.;
Dimension area;
int N=3;
//Rectangle R[]=new Rectangle[N],L[]=new Rectangle[N];
//Rectangle R2[]=new Rectangle[N],L2[]=new Rectangle[N];
//boolean Rs[]=new boolean[N],Ls[]=new boolean[N];
Image bgImage,fgImage;
Graphics gb,g;//background drawing
Color bgColor=Color.lightGray;
car c[]=new car[N];
Label XY;
String rts,STR[]={"Reset","Time"};
public void init() {
setBackground(bgColor);
for(int i=0;i if((rts=getParameter(STR[i]))!=null)
STR[i]=new String(rts);
}
Panel p=new Panel();
// p.add(new Label(STR[1]));
// p.add(timeField=new TextField("0.0",3));
// timeField.setEditable(false);
p.add(new Button(STR[0]));
p.add(iField=new TextField("",3));
iField.setEditable(false);
p.add(XY=new Label("(  X  ,  Y  )"));
//p.add(new Button("Start"));
add("North",p);
area=size();
area.height-=yOffset;
reset(true);// false for auto start
}

public boolean action(Event ev, Object arg) {
if (ev.target instanceof Button) {
String label = (String)arg;
if(label.equals("Reset")){
reset(true);
}/*else if(label.equals("Start")){
running=true;
start();
}*/
}else if(ev.target==iField&&changed!=null){
double val=Double.valueOf(iField.getText()).doubleValue();
if(mode int dval=5;
if(val>dval)dval=(int)val;
if(clickCount==2){
for(int i=0;i car.maxCount[i]=dval;
}
}else car.maxCount[mode]=dval;
}else{//Vmax
val=Math.abs(val);
if(clickCount==2){
for(int i=0;i car.vmax[i]=val;
}
}else car.vmax[mode%N]=val;
}
changed=null;
}
return true;
}
int xx,yy;
public void reset(boolean status){
time=0.;
clear(status);
}
String d2String(double value){
float f=(float)((int)(value*100.)/100.);
String str=String.valueOf(f);
if(str.indexOf(".")==-1)str+=".0";
return str;
}
// animation code
boolean running=true;
Thread animThread;
long startTime=0,lastTime;
long delay=50,delta;
//  This starts the threads.
public void start(){
//Start animating!
if (animThread == null) {
animThread = new Thread(this);
animThread.start();
}
//Remember the starting time. of thread
lastTime=startTime = System.currentTimeMillis();
}
public void stop() {
//Stop the animating thread.
animThread = null;
running=false;
}

public void run() {
//Just to be nice, lower this thread's priority
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
//This is the animation loop.
while (Thread.currentThread() == animThread) {
//Advance the animation frame. with delta time
delta=System.currentTimeMillis()-lastTime;
lastTime+=delta;
if(running)advanced(delta/1000.);
startTime+=delay;
try {
animThread.sleep(Math.max(0,startTime-System.currentTimeMillis()));
} catch (InterruptedException e) {
break;
}
}
}
void advanced(double dt){
for(int i=0;i c[i].advanced(dt);
time+=dt;
ts+=dt;
if(ts>1.){
ts-=1.;
//timeField.setText(String.valueOf(time));
}
repaint();
}
boolean rightClick=false;
Color cpass=Color.green,cstop=Color.red;
int mode;// 0-2:Nmax,3-5:Vmax,6-8:N
int clickCount;
int xs,ys;
public boolean mouseDown(Event e, int x, int y){
if((y-=yOffset)<0)return false;
clickCount=e.clickCount;
if(e.modifiers==Event.META_MASK){//"Right Click, ";
rightClick=true;
running=!running;
car.running=running;
repaint();
}else{
rightClick=false;
changed=null;
if(x for(int i=0;i if(carNmax[i].inside(x,y)){
mode=i;
changed=carNmax[i];
break;
}else if(carVmax[i].inside(x,y)){
mode=N+i;
changed=carVmax[i];
break;
//}else if(carN[i].inside(x,y)){
// mode=2*N+i;
// changed=carN[i];
// break;
}
}
if(changed!=null)iField.setEditable(true);//requestFocus();
else iField.setEditable(false);
}
xs=x;
ys=y;
return true;
}
public boolean mouseMove(Event e, int x, int y){
if((y-=yOffset)<0||running)return false;
XY.setText("("+x+", "+y+")");
return true;
}

public boolean mouseDrag(Event e, int x, int y){
if((y-=yOffset)<0||running)return false;
XY.setText("("+(xs-x)+", "+(y-ys)+")");
return true;
}
/*public boolean mouseUp(Event e, int x, int y){
if((y-=yOffset)<0)return false;
return true;
}*/
FontMetrics fm;
int chy,chy2;
int w=10,w2=2*w,dy,dx,dy2,xi,xf;
Rectangle carNmax[]=new Rectangle[N];
Rectangle carVmax[]=new Rectangle[N];
//Rectangle carN[]=new Rectangle[N];
Rectangle changed;
static int ds=80;
void clear(boolean status){
if(g==null){
bgImage = createImage(area.width, area.height);
gb = bgImage.getGraphics();
fgImage = createImage(area.width, area.height);
g = fgImage.getGraphics();
fm=gb.getFontMetrics();
chy=fm.getHeight();
chy2=chy*2;
car.init(g,w,area.width,area.height);
dy=area.height/N;
dy2=dy-w2;
dx=area.width-4*w;
yy=0;
xi=w+1;
xf=area.width-w;
int dd=dy2+xi;
for(int i=0;i /* R[i]=new Rectangle(xf,yy,xi,w);
R2[i]=new Rectangle(xf,yy+dd,xi,w);
L[i]=new Rectangle(0,yy+dd,xi,w);
L2[i]=new Rectangle(0,yy,xi,w);*/
carNmax[i]=new Rectangle(xx=car.xi2,yy=car.yi2[i]+chy,ds,chy);
//carN[i]=new Rectangle(xx+ds,yy,ds,chy);
carVmax[i]=new Rectangle(xx,yy+chy,ds,chy);
}
}else if(status)car.init(g,w,area.width,area.height);
gb.setColor(bgColor);
gb.fillRect(0, 0, area.width, area.height);
gb.setColor(Color.black);
gb.drawLine(0,0,area.width-1,0);
gb.drawRect(0,area.height-1,area.width-1,area.height-1);
yy=w;
for(int i=0;i gb.drawRect(0,yy,w,dy2);
gb.drawRect(w2,yy,dx,dy2);
gb.drawRect(area.width-w,yy,w,dy2);
c[i]=new car(i,0);
car.top[i]=c[i];
car.loop[i]=false;
}
gb.setColor(cstop);
/* for(int i=0;i Rs[i]=true;
Ls[i]=true;
drawRect(gb,R[i]);
drawRect(gb,L[i]);
}*/
gb.setColor(Color.gray);
yy-=(dy+w);
int yy2=yy-dy;
for(int i=0;i gb.drawLine(i,yy,i+w,yy);
gb.drawLine(i,yy2,i+w,yy2);
}
}
// void drawRect(Graphics g,Rectangle r){
// g.fillOval(r.x,r.y,r.width,r.height);
// }
public void paint(Graphics gs){
update(gs);
}
public void update(Graphics gs){
g.drawImage(bgImage, 0, 0, this);
g.drawString(STR[1]+d2String(time),area.width/2,25);
for(int i=0;i if(changed!=null){
g.setColor(Color.white);
if(clickCount==2){
int dh;
if(mode for(int i=0;i g.fillRect(changed.x,carNmax[i].y+dh,changed.width,changed.height);
}
} else g.fillRect(changed.x,changed.y,changed.width,changed.height);
}
g.setColor(Color.gray);
for(int i=0;i g.drawString("Nmax="+car.maxCount[i],xx=carNmax[i].x,yy=carNmax[i].y+chy);
g.drawString("N="+car.count[i],xx+ds,yy);
g.drawString("Vmax="+car.vmax[i],xx,yy+=chy);
g.drawString("n="+car.passed[i],xx+ds,yy);
}
// drawing work
gs.drawImage(fgImage, 0, yOffset, this);
}
}

class car extends rk4{
static int N=3,size,size2,size3,size0;
static int xmax,xmin,dy2;
static double ai=10.,vmax[]={20.,30.,40.}; // reaction time set to 1.0 sec
static double reactionTime=0.5,dmin[]=new double[N]
,dmin2[]=new double[N],dmax[]=new double[N];
static int xi,xf,yi[]=new int[N],yf[]=new int[N];
static int xi2,xf2,xi3,xf3,yi2[]=new int[N],yf2[]=new int[N];
static int maxCount[]={20,20,20},count[]={0,0,0},passed[]={0,0,0};
static car top[]=new car[3];
static boolean loop[]={false,false,false};
static double delta;
static car tmp=null;
static Graphics g;
//static boolean lastTurn=false;
int mode=0;// right,down,left,up
boolean turn=false;
boolean gone=false;
static boolean debug=false,running=true;
int X,Y,id;
double a;
car next=null;
double accelerated=1.,sign=1.;
//static int width=8,height=5;
car(int idi,int modei){
init(2,true);// 1D motion
id=idi;
mode=modei;
y[1]=vmax[id]/3.;//*Math.random();
if(mode==0){
Y=yi[id];
y[0]=xmin;
a=ai;
sign=1.;
}else{
mode=2;
Y=yf[id];
y[0]=xmax;
a=-ai;
sign=-1.;
y[1]=-y[1];
}
count[id]++;
gone=false;
}
static void init(Graphics gi,int w,int width,int height){
int y0=(int)(w/4.+0.5);
xmax=width;
xmin=0;
g=gi;
size=w/2;
size0=size/2;
size2=w;
size3=w*3/2;
xi=w+size-y0;
xf=width-w-size-y0;
xi2=xi+size2;
xf2=xf-size2;
xi3=xi2+size2;
xf3=xf2-size2;
height/=3;
int dy=height-w;
dy2=dy/2;
running=true;
for(int i=0;i yi[i]=y0;
yf[i]=yi[i]+dy;
yi2[i]=yi[i]+size;
yf2[i]=yf[i]-size;
setRange(i);
count[i]=0;
passed[i]=0;
}
}
static void setRange(int i){
dmin[i]=vmax[i]*reactionTime;
if(dmin[i] dmin2[i]=dmin[i]/2.;
if(dmin2[i] dmax[i]=dmin2[i]+size2;
}
public void derivs(double x,double y[],double dydx[]){
dydx[0]=y[1];
dydx[1]=a; //
}
void advanced(double dt){
//try{
switch(mode){//??????
case 0://right
X=(int)y[0];
if(gone)break;//??
//if(X>xf3&&y[0]!=0.)y[1]=-ai;
//else
if(y[0]>xf){
if(this!=top[id]&&next!=null && Math.random()>0.5){//??????????
gone=true;
y[1]=vmax[id];//????
//if(next!=null && next.y[1]==0.)next.a=next.sign*ai;
}else{//??
y[0]=yi[id];
y[1]=y[1]/2.;// ?
a=ai;
mode++;
sign=1.;
X=xf;
}
//if(next!=null )next.turn=true;
break;
}else if(y[0]>xf2&&next!=null&&next.mode==3)next.turn=true;
//if(turn&&X>xf2)y[1]/=2.;//?????????
if(next!=null&&next.turn){//????
if(X>xi2){
next.turn=false;//?????
if(next.y[1]==0.)next.a=next.sign*ai;
}else if(y[1]==0. && next.mode==3 && next.Y next.y[1]=0.;
next.a=0.;
}
}
break;
case 1://down  
if(y[0]>yf[id]){//?????
y[0]=xf;
a=-ai;
mode++;
y[1]=-y[1]/2.;
Y=yf[id];
sign=-1.;
//if(next!=null )next.turn=true;
break;
}else {
Y=(int)y[0];
if(y[0]>yf2[id]&&next!=null&&next.mode==0)next.turn=true;
}
//if(turn && Y>yf2[id])y[1]/=2.;
if(next!=null&&next.turn){//?????????
if(Y>yi2[id]){
next.turn=false;
if(next.y[1]==0.)next.a=next.sign*ai;
}else if(y[1]==0. &&next.mode==0&& next.X>xf2){//??????
next.y[1]=0.;
next.a=0.;
}
}
break;
case 2://left
X=(int)y[0];
if(gone)break;
//if(X //else
if(y[0] if(this!=top[id] && next!=null&& Math.random()>0.5){
gone=true;
y[1]=-vmax[id];
// if(next==null&&top[id].y[0]==0.]top[id].y[1]=top[id].sign*ai;
//if(next!=null && next.y[1]==0.)next.a=next.sign*ai;
}else{
y[0]=yf[id];
y[1]/=2.;
a=-ai;
mode++;
sign=-1.;
X=xi;
}
if(next==null)top[id].a=top[id].sign*ai;
//if(next!=null)next.turn=true;
if(this==top[id])loop[id]=true;//???
break;
}else if(y[0] //if(turn && X if(next!=null&&next.turn){
if(X next.turn=false;
if(next.y[1]==0.)next.a=next.sign*ai;
}else if(y[1]==0. &&next.mode==1&& next.Y>yf2[id]){
next.y[1]=0.;
next.a=0.;
}
}
break;
case 3://up
if(y[0] y[0]=xi;
a=ai;
mode=0;
sign=1.;
y[1]=-y[1]/2.;
Y=yi[id];
//if(next!=null )next.turn=true;
break;
}else{
Y=(int)y[0];
if(y[0] }
//if(turn && Y if(next!=null&&next.turn){
if(Y next.turn=false;
if(next.y[1]==0.)next.a=next.sign*ai;
}else if(y[1]==0. &&next.mode==2 && next.X next.y[1]=0.;
next.a=0.;
}
}
if(next==null&&turn&&top[id].y[1]==0.)
top[id].a=top[id].sign*ai;
break;
}
//} catch (NullPointerException e){ }
/*
if(gone){
y[0]+=y[1]*dt;
if(next!=null){
next.a=sign*ai;
next.advanced(dt);
}else {
top[id].a=sign*ai;
}
return;
}*/
//if(y[1]==0.)a=0.;
//???
if(count[id] y[0]=yi2[id]+dmin2[id];
y[1]=0.;
a=0.;
}else if(a!=0.){
nextmove(dt);
if(Math.abs(y[1])>vmax[id]){//????????????
y[1]=sign*vmax[id];
a=0.;
}
} else y[0]+=y[1]*dt;//?????
if(y[1]*sign<0.){//???????
y[1]=0.;
a=0.;
}

if(next!=null){//?????
if(next.gone){//???????
next.a=sign*ai;
}else if(next.mode==mode){//????
delta=sign*(y[0]-next.y[0]);//??
if(delta>dmax[id])next.accelerated=1.0; // ??
else if(Math.abs(delta) next.y[1]=0.;
next.accelerated=0.;
}else if(sign*(next.y[1]-y[1])>0.)next.accelerated=-1.;
if(Math.abs(next.y[1]) next.a=next.sign*ai*next.accelerated;
//if(next.a!=0&&next.y[1]==0.)next.y[1]=sign*0.1;
}else{//????
next.a=0.;
//next.y[1]=next.sign*vmax[id];
}
}//else {//????
// if(next.y[1]==0.&& (mode-next.mode>1. || !next.turn)) next.a=next.sign*ai;
else if(Math.abs(next.X-X)+Math.abs(next.Y-Y) next.y[1]=0.;
next.a=0.;
}
//}
next.advanced(dt);
if(next.X>xmax || next.X<0.){
next=next.next;
count[id]--;
passed[id]++;
}
/* if(loop[id] && count[id] if(mode==2 && X next.a=0.;
next.y[1]/=2.;
next.turn=true;
tmp=new car(id,2);
tmp.next=next;
next=tmp;
//}else if(mode==0 &&X>xi2){
// next.a=0.;
// next.y[1]/=2.;
// next.turn=true;
// tmp=new car(id,0);
// tmp.next=next;
// next=tmp;
}
}*/
}else{ // last car
if(loop[id]&&top[id].mode==mode){//????? ???
delta=sign*(y[0]-top[id].y[0]);
if(delta>dmax[id])top[id].accelerated=1.;
else if(Math.abs(delta) top[id].y[1]=0.;
top[id].accelerated=0.;
}else if(sign*(y[1]-top[id].y[1])>0.)top[id].accelerated=-1.;
if(Math.abs(top[id].y[1]) top[id].a=top[id].sign*ai*top[id].accelerated;
//if(top[id].a!=0.&&top[id].y[1]==0.)top[id].y[1]=0.1*sign;
}
/*/if(y[1]==0. && top[id].y[1]==0.)top[id].a=sign*ai;/*else{//????
top[id].a=0.;
top[id].y[1]=sign*vmax[id];
}*/
}else if(mode!=0 && top[id].y[1]==0.){//????
//if(mode!=0 || X>xi2)
top[id].a=top[id].sign*ai;
}
if( count[id] //if( (mode!=0 && top[id].mode>mode)  || X>xi2 && (top[id].mode!=3 || top[id].y[0]==yi2[id]+dmin2[id])&&
// (!loop[id] || top[id].mode>mode && top[id].y[0]>yi[id] || top[id].y[1]==0. ) )
if( top[id].mode>mode ||!loop[id]) {
if(X>xi2)next=new car(id,0);
}else if(top[id].mode==mode){
if(sign*(top[id].y[0]-y[0])>0)next=new car(id,0);
}
}else if(top[id].y[1]==0.){//????
if(mode!=0 || X>xi2)
top[id].a=top[id].sign*ai;
}
}
}
static int xx,yy;
void draw(){
//g.drawRect(X,Y,5,5);
if(a==0.){
if(y[1]!=0.)g.setColor(Color.green);
else g.setColor(Color.gray);
}else if(sign*a>0.)g.setColor(Color.blue);
else g.setColor(Color.red);
if(debug&&this==top[id])g.fillRect(X,Y,size,size);
else g.drawRect(X,Y,size,size);
if(!running){
g.setColor(Color.red);
if(mode%2==0)g.drawLine(xx=X+size0,yy=Y+size0,xx,yy+(int)y[1]);
else g.drawLine(xx=X+size0,yy=Y+size0,xx-(int)y[1],yy);
}
if(next!=null)next.draw();
}
}


[/quote]