3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * Gyas ROwers Mature At Cryogenic Speed
48 #include "gmx_fatal.h"
50 /* Units are meter and second */
53 int id
; /* Identification */
55 float v
; /* Position and velocity */
56 float vwanted
; /* Wants to drive at this speed */
57 float acc
; /* Acceleration */
58 float brake
; /* Break */
59 int lane
,oldlane
; /* Currently in lane */
60 gmx_bool bBrake
; /* Currently on the brakes */
61 unsigned long col
; /* Colour */
62 unsigned long roof
; /* Roof Colour */
66 int nlane
; /* Number of lanes on highway */
67 int metres
; /* Road length */
68 float dt
; /* Time step */
69 float min_dist
; /* Min distance cars can come */
70 int sleep
; /* How long to sleep in between updates */
73 static const char *Driving
[] = { "Start","Stop" };
74 static const char *Fogs
[] = { "Fog", "No Fog" };
75 enum buttons
{ Quit
, StartStop
, Fog
, NBUT
};
76 static const char *but_name
[NBUT
] = { "Quit", "Start", "Fog" };
83 gmx_bool bDriving
; /* Are we driving ? */
84 gmx_bool bFog
; /* Is it foggy ? */
90 int read_input(t_x11
*x11
,const char *fn
,t_car
**cars
,t_input
*ir
)
94 char buf
[100],b2
[100];
98 if (fscanf(in
,"%d %d %f %f %d",
99 &ir
->nlane
,&ir
->metres
,&ir
->dt
,&ir
->min_dist
,&ir
->sleep
) != 5)
100 gmx_fatal(FARGS
,"Not enough parameters in %s line 1",fn
);
101 if (fscanf(in
,"%d",&n
) != 1)
102 gmx_fatal(FARGS
,"Not enough parameters in %s line 2",fn
);
105 for(i
=0; (i
<n
); i
++) {
109 if (fscanf(in
,"%f %f %f %f %f %s %s",&(c
->x
),&(c
->v
),&(c
->vwanted
),
110 &(c
->acc
),&(c
->brake
),buf
,b2
) != 7)
111 gmx_fatal(FARGS
,"Not enough parameters in %s line %d",fn
,3+i
);
112 x11
->GetNamedColor(x11
,buf
,&(c
->col
));
113 x11
->GetNamedColor(x11
,b2
,&(c
->roof
));
120 static float get_dist(int ncars
,t_car cars
[],int which
,gmx_bool bFog
,
121 int dir
,int lane
,int metres
,int *nearest
)
132 for(i
=0; (i
<ncars
); i
++)
133 if ((i
!= which
) && (cars
[i
].oldlane
== lane
)){
134 nd
=cars
[i
].xold
-cars
[which
].xold
;
135 if ((nd
< 0) && (dir
> 0))
137 else if ((nd
> 0) && (dir
< 0))
140 if (!bFog
|| (fabs(nd
) < 50)) {
159 void simulate(t_x11
*x11
,t_xhighway
*xhw
,
160 int ncars
,t_car cars
[],t_input
*ir
)
162 int i
,n_bef
,n_bef1
,n_beh
;
163 float dist
,distf
,distb
;
165 for(i
=0; (i
<ncars
); i
++) {
166 cars
[i
].xold
=cars
[i
].x
;
167 cars
[i
].oldlane
=cars
[i
].lane
;
169 for(i
=0; (i
<ncars
); i
++) {
170 cars
[i
].bBrake
=FALSE
;
171 dist
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
172 1,cars
[i
].lane
,ir
->metres
,&n_bef
);
173 if (dist
< ir
->min_dist
) {
174 distf
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
175 1,cars
[i
].lane
+1,ir
->metres
,&n_bef1
);
176 distb
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
177 -1,cars
[i
].lane
+1,ir
->metres
,&n_beh
);
178 if ((cars
[i
].lane
< ir
->nlane
-1) && (distb
>= ir
->min_dist
) &&
179 (distf
>= ir
->min_dist
))
183 cars
[i
].v
-= cars
[i
].brake
*ir
->dt
;
187 if ((cars
[i
].v
< cars
[n_bef
].v
) && (dist
> ir
->min_dist
/2))
188 cars
[i
].v
=cars
[n_bef
].v
;
192 else if ((cars
[i
].lane
> 0) && (cars
[i
].v
== cars
[i
].vwanted
)) {
193 /* Check if I can go right again */
194 dist
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
195 1,cars
[i
].lane
-1,ir
->metres
,&n_bef
);
196 distb
=get_dist(ncars
,cars
,i
,xhw
->bFog
,
197 -1,cars
[i
].lane
-1,ir
->metres
,&n_beh
);
198 if ((dist
>= ir
->min_dist
) && (distb
>= ir
->min_dist
))
202 cars
[i
].x
+= cars
[i
].v
*ir
->dt
;
203 if (cars
[i
].x
> ir
->metres
)
204 cars
[i
].x
-= ir
->metres
;
205 if (!cars
[i
].bBrake
&& (cars
[i
].v
< cars
[i
].vwanted
)) {
206 cars
[i
].v
+= cars
[i
].acc
*ir
->dt
;
207 if (cars
[i
].v
> cars
[i
].vwanted
)
208 cars
[i
].v
= cars
[i
].vwanted
;
213 usleep(xhw
->ir
.sleep
);
214 ExposeWin(x11
->disp
,xhw
->win
.self
);
217 static void Configure(t_xhighway
*xhw
)
226 dw
=((float)(w
-2))/NBUT
-4;
227 for(i
=0; (i
<NBUT
); i
++) {
228 t_windata
*wd
=&(xhw
->but
[i
]);
231 InitWin(wd
,2+i
*(dw
+4),2,dw
,dh
,1,but_name
[i
]);
235 InitWin(&xhw
->win
,2,dh
+6,w
-6,h
-dh
-10,1,xhw
->main
.text
);
239 static void draw_car(Display
*disp
,Window wd
,GC gc
,
240 t_car
*car
,int w0
,int h0
)
253 XSetForeground(disp
,gc
,car
->col
);
254 XFillRectangle(disp
,wd
,gc
,w1
,h1
,w
,h
);
257 XSetForeground(disp
,gc
,car
->roof
);
258 XFillRectangle(disp
,wd
,gc
,w0
-wr
/2,h0
-hr
/2,wr
,hr
);
262 XSetForeground(disp
,gc
,YELLOW
);
267 XSetForeground(disp
,gc
,LIGHTRED
);
271 for(j
=1; (j
<jmax
); j
++) {
274 XDrawLine(disp
,wd
,gc
,w11
,h11
, w11
,h11
+hmax
);
275 XDrawLine(disp
,wd
,gc
,w11
,h11
+h
-hmax
,w11
,h11
+h
);
279 XSetForeground(disp
,gc
,WHITE
);
280 for(j
=1; (j
<3); j
++) {
283 XDrawLine(disp
,wd
,gc
,w11
,h11
, w11
,h11
+3);
284 XDrawLine(disp
,wd
,gc
,w11
,h11
+h
-3,w11
,h11
+h
);
288 static gmx_bool
xhwCallBack(struct t_x11
*x11
,XEvent
*event
, Window wd
, void *data
)
297 xhw
= (t_xhighway
*)data
;
301 nyy
=2*xhw
->ir
.nlane
+1;
304 for(i
=0; (i
<nyy
); i
++)
305 yy
[i
]=((float) i
*win
->height
)/(nyy
-1);
307 switch (event
->type
) {
309 if (wd
== win
->self
) {
310 sx
=(float)win
->width
/ xhw
->ir
.metres
;
312 XClearWindow(x11
->disp
,win
->self
);
313 XSetForeground(x11
->disp
,x11
->gc
,WHITE
);
315 for(i
=2; (i
<nyy
-1); i
+=2)
316 XDrawLine(x11
->disp
,win
->self
,x11
->gc
,0,yy
[i
],win
->width
-1,yy
[i
]);
318 for(i
=0; (i
<xhw
->ncars
); i
++) {
319 t_car
*car
=&(xhw
->cars
[i
]);
321 int h1
=yy
[1+2*(xhw
->ir
.nlane
-1-car
->lane
)];
323 draw_car(x11
->disp
,win
->self
,x11
->gc
,car
,w1
,h1
);
326 simulate(x11
,xhw
,xhw
->ncars
,xhw
->cars
,&xhw
->ir
);
330 case ConfigureNotify
:
331 if (wd
== xhw
->main
.self
) {
332 xhw
->main
.width
=event
->xconfigure
.width
;
333 xhw
->main
.height
=event
->xconfigure
.height
;
335 for(i
=0; (i
<NBUT
); i
++)
336 XMoveResizeWindow(x11
->disp
,xhw
->but
[i
].self
,
337 xhw
->but
[i
].x
,xhw
->but
[i
].y
,
338 xhw
->but
[i
].width
,xhw
->but
[i
].height
);
339 XMoveResizeWindow(x11
->disp
,win
->self
,
340 win
->x
,win
->y
,win
->width
,win
->height
);
342 else if (wd
== win
->self
) {
343 win
->width
=event
->xconfigure
.width
;
344 win
->height
=event
->xconfigure
.height
;
355 static gmx_bool
butCallBack(struct t_x11
*x11
,XEvent
*event
, Window wd
, void *data
)
357 XSetWindowAttributes attr
;
363 xhw
= (t_xhighway
*)data
;
364 for(i
=0; (i
<NBUT
); i
++) {
365 if (xhw
->but
[i
].self
== wd
)
369 fprintf(stderr
,"Incorrect window: %x in butcallback\n",(unsigned)wd
);
374 switch (event
->type
) {
376 XClearWindow(x11
->disp
,win
->self
);
379 label
=Driving
[xhw
->bDriving
];
382 label
=Fogs
[xhw
->bFog
];
387 XSetForeground(x11
->disp
,x11
->gc
,WHITE
);
388 TextInWin(x11
,win
,label
,eXCenter
,eYCenter
);
391 case ConfigureNotify
:
392 win
->width
=event
->xconfigure
.width
;
393 win
->height
=event
->xconfigure
.height
;
400 xhw
->bDriving
=1-xhw
->bDriving
;
401 ExposeWin(x11
->disp
,win
->self
);
403 ExposeWin(x11
->disp
,xhw
->win
.self
);
406 xhw
->bFog
=1-xhw
->bFog
;
408 attr
.background_pixel
=DARKGREY
;
410 attr
.background_pixel
=BLACK
;
411 XChangeWindowAttributes(x11
->disp
,xhw
->win
.self
,CWBackPixel
,&attr
);
412 /*ExposeWin(x11->disp,win->self);*/
424 t_xhighway
*GetXHW(t_x11
*x11
,const char *infile
)
428 char progname
[STRLEN
];
431 xhw
->ncars
=read_input(x11
,infile
,&(xhw
->cars
),&xhw
->ir
);
436 strncpy(progname
,Program(),STRLEN
-1);
437 InitWin(&xhw
->main
,0,0,w
,h
+dh
+7,1,progname
);
438 xhw
->main
.self
=XCreateSimpleWindow(x11
->disp
,x11
->root
,
439 xhw
->main
.x
,xhw
->main
.y
,
440 xhw
->main
.width
,xhw
->main
.height
,
441 xhw
->main
.bwidth
,WHITE
,BLACK
);
442 x11
->RegisterCallback(x11
,xhw
->main
.self
,0,xhwCallBack
,xhw
);
443 x11
->SetInputMask(x11
,xhw
->main
.self
,ButtonPressMask
| ExposureMask
|
444 StructureNotifyMask
);
448 for(i
=0; (i
<NBUT
); i
++) {
449 t_windata
*wd
=&(xhw
->but
[i
]);
451 wd
->self
=XCreateSimpleWindow(x11
->disp
,xhw
->main
.self
,
453 wd
->width
,wd
->height
,
454 wd
->bwidth
,WHITE
,BLACK
);
455 x11
->RegisterCallback(x11
,wd
->self
,xhw
->main
.self
,
457 x11
->SetInputMask(x11
,wd
->self
,ButtonPressMask
| ExposureMask
|
458 StructureNotifyMask
);
461 xhw
->win
.self
=XCreateSimpleWindow(x11
->disp
,xhw
->main
.self
,
462 xhw
->win
.x
,xhw
->win
.y
,
463 xhw
->win
.width
,xhw
->win
.height
,
464 xhw
->win
.bwidth
,WHITE
,BLACK
);
465 x11
->RegisterCallback(x11
,xhw
->win
.self
,0,xhwCallBack
,xhw
);
466 x11
->SetInputMask(x11
,xhw
->win
.self
,ButtonPressMask
| ExposureMask
|
467 StructureNotifyMask
);
472 int main(int argc
,char *argv
[])
474 const char *desc
[] = {
475 "[TT]highway[tt] is the GROMCAS highway simulator. It is an X-windows",
476 "gadget that shows a (periodic) Autobahn with a user defined",
477 "number of cars. Fog can be turned on or off to increase the",
478 "number of crashes. Nice for a background CPU-eater. A sample",
479 "input file is in [TT]$GMXDATA/top/highway.dat[tt]"
485 { efDAT
, "-f", "highway", ffREAD
}
487 #define NFILE asize(fnm)
489 CopyRight(stderr
,argv
[0]);
490 parse_common_args(&argc
,argv
,0,NFILE
,fnm
,
491 0,NULL
,asize(desc
),desc
,0,NULL
,&oenv
);
493 if ((x11
=GetX11(&argc
,argv
))==NULL
) {
494 fprintf(stderr
,"Can't connect to X Server.\n"
495 "Check your DISPLAY environment variable\n");
498 xhw
=GetXHW(x11
,opt2fn("-f",NFILE
,fnm
));
500 XMapWindow(x11
->disp
,xhw
->main
.self
);
501 XMapSubwindows(x11
->disp
,xhw
->main
.self
);