#include #include #include #include "gene.h" #define TITLE "L3" #define ButtonPad 10 extern int WorldWidth, WorldHeight, MaxGeneration; extern unsigned char MessageStdout; extern unsigned long Step, Generation; extern unsigned char FullScreen, AutoDemo, WireFrameMode; Display *dpy; Window RootWin, MainWin, win, msgwin; int screen, depth; GC gc; XGCValues gcv; unsigned long fg, bg; XFontStruct *fst; static XSetWindowAttributes att; static int WinX = 0, WinY = 0; static int WinWidth, WinHeight; static int ButtonWidth, ButtonHeight, ButtonX, ButtonBase, InfoTopBase; unsigned long ButtonFG, ButtonBG, WorkBG; void b_run(), b_gene(), b_sele(), b_step(), b_replay(), b_dump(), b_reset(), b_show_mode(), b_load(), b_save(), b_quit(); struct button_rec { char *label; void (*proc)(); int flag; Window win; } buttons[] = { {"Run", b_run, 0}, {"Generation", b_gene, 0}, {"Selection", b_sele, 0}, {"Step", b_step, 0}, {"Replay", b_replay, 0}, {"Replay & Dump", b_dump, 0}, {"Display mode", b_show_mode, 0}, {"Reset", b_reset, 0}, {"Load", b_load, 0}, {"Save", b_save, 0}, {"Quit", b_quit, 0}, { NULL, b_quit, 0 } }; parse_geom(str) char *str; { XParseGeometry(str,&WinX,&WinY,&WorldWidth,&WorldHeight); } gr_init(argc,argv) int argc; char **argv; { int w; struct button_rec *b; extern char *DisplayName, *FontName; if(!(dpy = XOpenDisplay(DisplayName))) { fprintf(stderr,"%s: cannot open %s.\n",argv[0], XDisplayName(DisplayName)); exit(1); } screen = DefaultScreen(dpy); if ((depth = DefaultDepth(dpy,screen)) < 8) { fprintf(stderr,"%s: has %d planes though required 8 or more.", XDisplayName(DisplayName),depth); exit(1); } if (!(fst = XLoadQueryFont(dpy, FontName))) { fprintf(stderr,"%s: has not font %s.\n", XDisplayName(DisplayName), FontName); exit(1); } color_setup(); for (ButtonWidth = 0, b = buttons; b->label; b ++) { w = XTextWidth(fst,b->label,strlen(b->label)) + fst->max_bounds.width; if (ButtonWidth < w) ButtonWidth = w; } if (FullScreen) { WinX = WinY = 0; WorldWidth = DisplayWidth(dpy,screen)-ButtonWidth-ButtonPad*2; WorldHeight = DisplayHeight(dpy,screen); if (WorldHeight > WorldWidth) { WinY = lrand48() % (WorldHeight - WorldWidth + 1); WorldHeight = WorldWidth; } else if (WorldWidth > WorldHeight) { WinX = lrand48() % (WorldWidth - WorldHeight + 1); WorldWidth = WorldHeight; } } ButtonX = WorldWidth + ButtonPad; WinWidth = ButtonX + ButtonWidth + ButtonPad; WinHeight = WorldHeight; ButtonHeight = (fst->max_bounds.ascent + fst->max_bounds.descent) * 1.5; ButtonBase = ButtonHeight * 0.2 + fst->max_bounds.ascent; RootWin = DefaultRootWindow(dpy); MainWin = XCreateSimpleWindow(dpy,RootWin, WinX, WinY, WinWidth, WinHeight, (FullScreen?0:1), fg, bg); XSetStandardProperties(dpy, MainWin, TITLE, argv[0], None, argv, argc, NULL); att.event_mask = ExposureMask | ResizeRedirectMask | ButtonPressMask | ButtonReleaseMask; XSelectInput(dpy,MainWin,att.event_mask); if (FullScreen) { att.override_redirect = True; XChangeWindowAttributes(dpy,MainWin,CWOverrideRedirect,&att); } win = XCreateSimpleWindow(dpy,MainWin, 0, 0, WorldWidth, WorldHeight, 0, fg, bg); XSelectInput(dpy,win,ButtonPressMask|ButtonReleaseMask|ExposureMask); for (w = ButtonPad, b = buttons; b->label; b ++) { b->win = XCreateSimpleWindow(dpy,MainWin,ButtonX,w, ButtonWidth,ButtonHeight,1,ButtonFG,ButtonBG); XSelectInput(dpy,b->win,ExposureMask| ButtonPressMask|ButtonReleaseMask| EnterWindowMask|LeaveWindowMask); XMapRaised(dpy,b->win); w += ButtonHeight + ButtonPad; } InfoTopBase = w + ButtonHeight; if (!MessageStdout && !FullScreen) { msgwin = XCreateSimpleWindow(dpy,RootWin,0,0,100,100,1,fg,bg); att.override_redirect = True; XChangeWindowAttributes(dpy,msgwin,CWOverrideRedirect,&att); XSelectInput(dpy,msgwin,ExposureMask); } gcv.foreground = fg; gcv.background = bg; gcv.font = fst->fid; gc = XCreateGC(dpy,win,GCForeground|GCBackground|GCFont,&gcv); draw_init(); XMapRaised(dpy, MainWin); XMapRaised(dpy, win); XFlush(dpy); } color_setup() { XColor scr, exc; Colormap cmap = DefaultColormap(dpy,screen); extern unsigned char BlackBackground; XAllocNamedColor(dpy,cmap,"NavyBlue",&scr,&exc); ButtonFG = scr.pixel; XAllocNamedColor(dpy,cmap,"SkyBlue",&scr,&exc); ButtonBG = scr.pixel; XAllocNamedColor(dpy,cmap,"grey50",&scr,&exc); WorkBG = scr.pixel; if (BlackBackground) { bg = BlackPixel(dpy,screen); fg = WhitePixel(dpy,screen); } else { bg = WhitePixel(dpy,screen); fg = BlackPixel(dpy,screen); } } event_loop() { XEvent event; while (1) { XNextEvent(dpy,&event); switch (event.type) { case Expose: if (!event.xexpose.count) redisplay(&event); break; case EnterNotify: case LeaveNotify: redraw_button(&event); break; case ButtonRelease: if (!AutoDemo) exec_button(&event); } } } check_event() { XEvent event; while (XCheckMaskEvent(dpy,ButtonPressMask|ButtonReleaseMask| ExposureMask,&event)) switch (event.type) { case ButtonRelease: return True; case Expose: if (!event.xexpose.count) redisplay(&event); } return False; } demo_loop() { int flag; XEvent event; do XNextEvent(dpy,&event); while (event.type != Expose || event.xexpose.count); redisplay(&event); do { while (XCheckMaskEvent(dpy,ButtonPressMask|ButtonReleaseMask| ExposureMask,&event)) switch (event.type) { case ButtonRelease: exit(1); case Expose: if (!event.xexpose.count) redisplay(&event); } flag = exec_one_step(); XFlush(dpy); if (!flag) { if (MaxGeneration && Generation >= MaxGeneration) flag = 2; else selection(); } } while (flag != 2); sleep(4); exit(0); } redraw_button(e) XCrossingEvent *e; { struct button_rec *b; for (b = buttons; b->label; b ++) if (e->window == b->win) { b->flag = (e->type == EnterNotify); draw_button(b); break; } } exec_button(e) XButtonEvent *e; { struct button_rec *b; for (b = buttons; b->label; b ++) if (e->window == b->win) { (*b->proc)(); break; } if (e->window == win) switch (e->button) { case Button1: switch_draw_mode(e->x,e->y); break; case Button2: show_individual(e->x,e->y); } } draw_button(b) struct button_rec *b; { unsigned long bfg = ButtonFG, bbg = ButtonBG; int x; if (b->flag) { bfg = ButtonBG; bbg = ButtonFG; } XSetForeground(dpy,gc,bbg); XFillRectangle(dpy,b->win,gc,0,0,ButtonWidth,ButtonHeight); x = (ButtonWidth - XTextWidth(fst,b->label,strlen(b->label))) / 2; XSetForeground(dpy,gc,bfg); XDrawString(dpy,b->win,gc,x,ButtonBase,b->label,strlen(b->label)); } void b_run() { go_forward(1); } void b_gene() { go_forward(0); } go_forward(cont) int cont; { int flag; draw_message("Click mouse button to stop."); do { flag = exec_one_step(); XFlush(dpy); if (MaxGeneration && Generation > MaxGeneration) world_reset(); else if (!flag && cont) selection(); } while ((flag || cont) && !check_event()); if (!MessageStdout && !FullScreen) XUnmapWindow(dpy,msgwin); } void b_sele() { selection(); } void b_step() { exec_one_step(); } void b_replay() { replay(0); } void b_dump() { replay(1); } replay(dump) int dump; { int SavedStep = Step; for (Step = 0; Step <= SavedStep; Step ++) { redraw_world(); if (dump) dump_screen(); } Step = SavedStep; } void b_show_mode() { WireFrameMode = ! WireFrameMode; redraw_world(); } void b_reset() { world_reset(); } void b_quit() { exit(0); } char MassageString[1300]; draw_message(msg) char *msg; { int len, x, y, w, h, ww, wh, bw, d; Window cwin, root,parent,*children; if (MessageStdout) { puts(msg); return; } else if (FullScreen) return; strcpy(MassageString,msg); for (w = 0, h = ButtonHeight; *msg; msg += len) { if (*msg == '\n') { msg ++; h += ButtonHeight; } for (len = 0; msg[len] && msg[len] != '\n'; len++); if (len && w < (ww = XTextWidth(fst,msg,len))) w = ww; } parent = MainWin; do { cwin = parent; XQueryTree(dpy,cwin,&root,&parent,&children,&d); } while (root != parent); XGetGeometry(dpy,cwin,&root,&x,&y,&ww,&wh,&bw,&d); XMoveResizeWindow(dpy,msgwin,x,y+wh+bw+1,w+ButtonPad*2,h); XMapRaised(dpy,msgwin); display_message(); } display_message() { int len, y; char *msg; XSetForeground(dpy,gc,fg); for (msg = MassageString, y = ButtonBase; *msg; msg += len) { if (*msg == '\n') { msg ++; y += ButtonHeight; } for (len = 0; msg[len] && msg[len] != '\n'; len++); if (len) XDrawImageString(dpy,msgwin,gc,ButtonPad,y,msg,len); } } draw_info() { char buf[32]; int base; unsigned long **p; extern unsigned long PopSize, Generation, Step, BestScore; static unsigned long *info[] = { &Generation, &Step, &BestScore, &PopSize, NULL, }; XSetForeground(dpy,gc,fg); for (p = info, base = InfoTopBase; *p; p ++, base += ButtonHeight) { sprintf(buf,"%5d",**p); XDrawImageString(dpy,MainWin,gc,ButtonX,base,buf,strlen(buf)); } } redisplay(e) XExposeEvent *e; { struct button_rec *b; Cell *p; if (e->window == MainWin) { XSetForeground(dpy,gc,WorkBG); XFillRectangle(dpy,MainWin,gc,WorldWidth,0, WinWidth-WorldWidth,WinHeight); draw_info(); } else if (e->window == win) { redisplay_world(); } else if (e->window == msgwin) { display_message(); } else for (b = buttons; b->label; b ++) if (e->window == b->win) { draw_button(b); break; } }