4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
12 * Copyright (c) 1991-2001
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License
18 * as published by the Free Software Foundation; either version 2
19 * of the License, or (at your option) any later version.
21 * If you want to redistribute modifications, please consider that
22 * scientific software is very special. Version control is crucial -
23 * bugs must be traceable. We will be happy to consider code for
24 * inclusion in the official distribution, but derived work must not
25 * be called official GROMACS. Details are found in the README & COPYING
26 * files - if they are missing, get the official version at www.gromacs.org.
28 * To help us fund GROMACS development, we humbly ask that you cite
29 * the papers on the package - you can find them in the top README file.
31 * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
34 * Giving Russians Opium May Alter Current Situation
36 static char *SRCID_highway_c = "$Id$";
46 /* Units are meter and second */
49 int id; /* Identification */
51 float v; /* Position and velocity */
52 float vwanted; /* Wants to drive at this speed */
53 float acc; /* Acceleration */
54 float brake; /* Break */
55 int lane,oldlane; /* Currently in lane */
56 bool bBrake; /* Currently on the brakes */
57 unsigned long col; /* Colour */
58 unsigned long roof; /* Roof Colour */
62 int nlane; /* Number of lanes on highway */
63 int metres; /* Road length */
64 float dt; /* Time step */
65 float min_dist; /* Min distance cars can come */
68 static char *Driving[] = { "Start","Stop" };
69 static char *Fogs[] = { "Fog", "No Fog" };
70 enum buttons { Quit, StartStop, Fog, NBUT };
71 static char *but_name[NBUT] = { "Quit", "Start", "Fog" };
78 bool bDriving; /* Are we driving ? */
79 bool bFog; /* Is it foggy ? */
85 int read_cars(t_x11 *x11,char *fn,t_car **cars)
89 char buf[100],b2[100];
96 for(i=0; (i<n); i++) {
100 fscanf(in,"%d %f %f %f %f %s %s",
101 &(c->x),&(c->v),&(c->vwanted),&(c->acc),&(c->brake),buf,b2);
102 x11->GetNamedColor(x11,buf,&(c->col));
103 x11->GetNamedColor(x11,b2,&(c->roof));
110 t_input *read_input(char *fn)
118 fscanf(in,"%d %d %f %f",&ir->nlane,&ir->metres,&ir->dt,&ir->min_dist);
124 static float get_dist(int ncars,t_car cars[],int which,bool bFog,
125 int dir,int lane,int metres,int *nearest)
136 for(i=0; (i<ncars); i++)
137 if ((i != which) && (cars[i].oldlane == lane)){
138 nd=cars[i].xold-cars[which].xold;
139 if ((nd < 0) && (dir > 0))
141 else if ((nd > 0) && (dir < 0))
144 if (!bFog || (fabs(nd) < 50)) {
163 void simulate(t_x11 *x11,t_xhighway *xhw,
164 int ncars,t_car cars[],t_input *ir)
166 int i,n_bef,n_bef1,n_beh;
167 float dist,distf,distb;
169 for(i=0; (i<ncars); i++) {
170 cars[i].xold=cars[i].x;
171 cars[i].oldlane=cars[i].lane;
173 for(i=0; (i<ncars); i++) {
174 cars[i].bBrake=FALSE;
175 dist=get_dist(ncars,cars,i,xhw->bFog,
176 1,cars[i].lane,ir->metres,&n_bef);
177 if (dist < ir->min_dist) {
178 distf=get_dist(ncars,cars,i,xhw->bFog,
179 1,cars[i].lane+1,ir->metres,&n_bef1);
180 distb=get_dist(ncars,cars,i,xhw->bFog,
181 -1,cars[i].lane+1,ir->metres,&n_beh);
182 if ((cars[i].lane < ir->nlane-1) && (distb >= ir->min_dist) &&
183 (distf >= ir->min_dist))
187 cars[i].v -= cars[i].brake*ir->dt;
191 if ((cars[i].v < cars[n_bef].v) && (dist > ir->min_dist/2))
192 cars[i].v=cars[n_bef].v;
196 else if ((cars[i].lane > 0) && (cars[i].v == cars[i].vwanted)) {
197 /* Check if I can go right again */
198 dist=get_dist(ncars,cars,i,xhw->bFog,
199 1,cars[i].lane-1,ir->metres,&n_bef);
200 distb=get_dist(ncars,cars,i,xhw->bFog,
201 -1,cars[i].lane-1,ir->metres,&n_beh);
202 if ((dist >= ir->min_dist) && (distb >= ir->min_dist))
206 cars[i].x += cars[i].v*ir->dt;
207 if (cars[i].x > ir->metres)
208 cars[i].x -= ir->metres;
209 if (!cars[i].bBrake && (cars[i].v < cars[i].vwanted)) {
210 cars[i].v += cars[i].acc*ir->dt;
211 if (cars[i].v > cars[i].vwanted)
212 cars[i].v = cars[i].vwanted;
217 ExposeWin(x11->disp,xhw->win.self);
220 static void Configure(t_xhighway *xhw)
229 dw=((float)(w-2))/NBUT-4;
230 for(i=0; (i<NBUT); i++) {
231 t_windata *wd=&(xhw->but[i]);
234 InitWin(wd,2+i*(dw+4),2,dw,dh,1,but_name[i]);
238 InitWin(&xhw->win,2,dh+6,w-6,h-dh-10,1,xhw->main.text);
242 static void draw_car(Display *disp,Window wd,GC gc,
243 t_car *car,int w0,int h0)
256 XSetForeground(disp,gc,car->col);
257 XFillRectangle(disp,wd,gc,w1,h1,w,h);
260 XSetForeground(disp,gc,car->roof);
261 XFillRectangle(disp,wd,gc,w0-wr/2,h0-hr/2,wr,hr);
265 XSetForeground(disp,gc,YELLOW);
270 XSetForeground(disp,gc,LIGHTRED);
274 for(j=1; (j<jmax); j++) {
277 XDrawLine(disp,wd,gc,w11,h11, w11,h11+hmax);
278 XDrawLine(disp,wd,gc,w11,h11+h-hmax,w11,h11+h);
282 XSetForeground(disp,gc,WHITE);
283 for(j=1; (j<3); j++) {
286 XDrawLine(disp,wd,gc,w11,h11, w11,h11+3);
287 XDrawLine(disp,wd,gc,w11,h11+h-3,w11,h11+h);
291 static bool xhwCallBack(struct t_x11 *x11,XEvent *event, Window wd, void *data)
300 xhw = (t_xhighway *)data;
304 nyy=2*xhw->ir->nlane+1;
307 for(i=0; (i<nyy); i++)
308 yy[i]=((float) i*win->height)/(nyy-1);
310 switch (event->type) {
312 if (wd == win->self) {
313 sx=(float)win->width / xhw->ir->metres;
315 XClearWindow(x11->disp,win->self);
316 XSetForeground(x11->disp,x11->gc,WHITE);
318 for(i=2; (i<nyy-1); i+=2)
319 XDrawLine(x11->disp,win->self,x11->gc,0,yy[i],win->width-1,yy[i]);
321 for(i=0; (i<xhw->ncars); i++) {
322 t_car *car=&(xhw->cars[i]);
324 int h1=yy[1+2*(xhw->ir->nlane-1-car->lane)];
326 draw_car(x11->disp,win->self,x11->gc,car,w1,h1);
329 simulate(x11,xhw,xhw->ncars,xhw->cars,xhw->ir);
333 case ConfigureNotify:
334 if (wd == xhw->main.self) {
335 xhw->main.width=event->xconfigure.width;
336 xhw->main.height=event->xconfigure.height;
338 for(i=0; (i<NBUT); i++)
339 XMoveResizeWindow(x11->disp,xhw->but[i].self,
340 xhw->but[i].x,xhw->but[i].y,
341 xhw->but[i].width,xhw->but[i].height);
342 XMoveResizeWindow(x11->disp,win->self,
343 win->x,win->y,win->width,win->height);
345 else if (wd == win->self) {
346 win->width=event->xconfigure.width;
347 win->height=event->xconfigure.height;
358 static bool butCallBack(struct t_x11 *x11,XEvent *event, Window wd, void *data)
360 XSetWindowAttributes attr;
366 xhw = (t_xhighway *)data;
367 for(i=0; (i<NBUT); i++) {
368 if (xhw->but[i].self == wd)
372 fprintf(stderr,"Incorrect window: %x in butcallback\n",(unsigned)wd);
377 switch (event->type) {
379 XClearWindow(x11->disp,win->self);
382 label=Driving[xhw->bDriving];
385 label=Fogs[xhw->bFog];
390 XSetForeground(x11->disp,x11->gc,WHITE);
391 TextInWin(x11,win,label,eXCenter,eYCenter);
394 case ConfigureNotify:
395 win->width=event->xconfigure.width;
396 win->height=event->xconfigure.height;
403 xhw->bDriving=1-xhw->bDriving;
404 ExposeWin(x11->disp,win->self);
406 ExposeWin(x11->disp,xhw->win.self);
409 xhw->bFog=1-xhw->bFog;
411 attr.background_pixel=DARKGREY;
413 attr.background_pixel=BLACK;
414 XChangeWindowAttributes(x11->disp,xhw->win.self,CWBackPixel,&attr);
415 /*ExposeWin(x11->disp,win->self);*/
427 t_xhighway *GetXHW(t_x11 *x11,char *infile,char *carfile)
434 xhw->ir=read_input(infile);
435 xhw->ncars=read_cars(x11,carfile,&(xhw->cars));
440 InitWin(&xhw->main,0,0,w,h+dh+7,1,Program());
441 xhw->main.self=XCreateSimpleWindow(x11->disp,x11->root,
442 xhw->main.x,xhw->main.y,
443 xhw->main.width,xhw->main.height,
444 xhw->main.bwidth,WHITE,BLACK);
445 x11->RegisterCallback(x11,xhw->main.self,0,xhwCallBack,xhw);
446 x11->SetInputMask(x11,xhw->main.self,ButtonPressMask | ExposureMask |
447 StructureNotifyMask);
451 for(i=0; (i<NBUT); i++) {
452 t_windata *wd=&(xhw->but[i]);
454 wd->self=XCreateSimpleWindow(x11->disp,xhw->main.self,
456 wd->width,wd->height,
457 wd->bwidth,WHITE,BLACK);
458 x11->RegisterCallback(x11,wd->self,xhw->main.self,
460 x11->SetInputMask(x11,wd->self,ButtonPressMask | ExposureMask |
461 StructureNotifyMask);
464 xhw->win.self=XCreateSimpleWindow(x11->disp,xhw->main.self,
465 xhw->win.x,xhw->win.y,
466 xhw->win.width,xhw->win.height,
467 xhw->win.bwidth,WHITE,BLACK);
468 x11->RegisterCallback(x11,xhw->win.self,0,xhwCallBack,xhw);
469 x11->SetInputMask(x11,xhw->win.self,ButtonPressMask | ExposureMask |
470 StructureNotifyMask);
475 int main(int argc,char *argv[])
477 static char *desc[] = {
478 "highway is the gromacs highway simulator. It is an X-windows",
479 "gadget that shows a (periodic) autobahn with a user defined",
480 "number of cars. Fog can be turned on or off to increase the",
481 "number of crashes. Nice for a background CPU-eater"
486 { efDAT, "-f", "highway", ffREAD },
487 { efDAT, "-a", "auto", ffREAD }
489 #define NFILE asize(fnm)
491 CopyRight(stdout,argv[0]);
492 parse_common_args(&argc,argv,PCA_CAN_TIME,FALSE,NFILE,fnm,
493 0,NULL,asize(desc),desc,0,NULL);
495 if ((x11=GetX11(&argc,argv))==NULL) {
496 fprintf(stderr,"Can't connect to X Server.\n"
497 "Check your DISPLAY environment variable\n");
500 xhw=GetXHW(x11,opt2fn("-f",NFILE,fnm),opt2fn("-a",NFILE,fnm));
502 XMapWindow(x11->disp,xhw->main.self);
503 XMapSubwindows(x11->disp,xhw->main.self);