📄 xhamster.c
字号:
static pid_t pid = -1; /* child process identifier */static FILE *p_in; /* input pipe (to be read from) */static FILE *p_out; /* output pipe (to be written to) */static XtInputId ip_pipe; /* pipe input procedure identifier *//* --- hamster variables --- */static Pixmap hms_bmap; /* bitmap of hamster sprite */static MAZE *maze; /* maze the hamster is in */static HMSCB hmscb[1] = { /* hamster control blocks */ { NULL, NULL, "\0"} }; /* (at most one hamster) */static int xoff, yoff; /* offsets for drawing */static int running = 0; /* whether hamster is running *//*---------------------------------------------------------------------- Auxiliary Functions----------------------------------------------------------------------*/static void dcb_nop (Widget widget, XtPointer client, XtPointer call){ /* --- close dialog box (callback) */ while (XtClass(widget) != transientShellWidgetClass) widget = XtParent(widget); /* find the shell widget */ XtPopdown(widget); /* close dialog box */ mn_enable(menu, MN_MENU, 1); /* and enable menu bar */} /* dcb_nop() *//*--------------------------------------------------------------------*/static void dcb_alert (Widget widget, XtPointer client, XtPointer call){ /* --- close dialog box (callback) */ while (XtClass(widget) != transientShellWidgetClass) widget = XtParent(widget); /* find the shell widget */ XtPopdown(widget); /* close dialog box */ mn_enable(menu, MN_MENU, 1); /* and enable menu bar */ if (running) result(); /* if hamster is running, show result */} /* dcb_nop() *//*--------------------------------------------------------------------*/static void error (int code, ...){ /* --- print error message */ va_list va; /* list of variable arguments */ const ERRMSG *msg; /* error message */ String argv[8]; /* variable argument vector */ Cardinal argc; /* number of arguments */ if ((code > 0) || (code < E_UNKNOWN)) code = E_UNKNOWN; /* check error code */ msg = errmsgs -code; /* get error message data and */ va_start(va, code); /* list of variable arguments */ for (argc = 0; argc < (Cardinal)msg->argc; argc++) argv[argc] = va_arg(va, String); va_end(va); /* get message arguments */ argc = msg->argc; /* get number of arguments */ if (strcmp(msg->name, "error") == 0) /* if name is ``error'' */ XtAppErrorMsg(appctx, msg->name, msg->type, msg->class, msg->dflt, argv, &argc); /* print error message */ else { /* if name is ``warning'' */ XtAppGetErrorDatabaseText(appctx, msg->name, msg->type, msg->class, msg->dflt, fmt, FMT_MAX, NULL); va_start(va, code); /* list of variable arguments */ vsprintf(buf, fmt, va); /* get and format message */ va_end(va); /* end variable argument evaluation */ mn_enable(menu, MN_MENU,0); /* disable menu bar and show dialog */ if (db_alert(w_top, dcb_alert, buf) != 0) { mn_enable(menu, MN_MENU, 1); /* enable menu bar */ XtAppWarningMsg(appctx, msg->name, msg->type, msg->class, msg->dflt, argv, &argc);/* if the alert dialog box */ } /* cannot be shown, */ } /* print a warning message */} /* error() *//*--------------------------------------------------------------------*/static double drand (void){ /* --- compute random number in [0,1) */ return rand() /(RAND_MAX +1.0);} /* drand() *//*---------------------------------------------------------------------- Drawing Functions----------------------------------------------------------------------*/static void draw_field (int x, int y){ /* --- draw maze field */ short c, t; /* contents of maze field and buffer */ short cw, ce, cs, cn; /* contents of surrounding fields */ c = mz_getfld(maze, x, y); /* get contents of */ cw = mz_getfld(maze, x-1, y); /* field to draw */ ce = mz_getfld(maze, x+1, y); /* and contents of */ cs = mz_getfld(maze, x, y-1); /* surrounding fields */ cn = mz_getfld(maze, x, y+1); x = xoff +x *FIELDWD; /* multiply coordinates with */ y = yoff -y *FIELDWD; /* field width and add offsets */ /* --- draw field interior --- */ XSetForeground(display, gc, (c & MZ_HOME) ? grey : white); XFillRectangle(display, window, gc, x, y -FIELDWD+2, FIELDWD-1, FIELDWD-1); /* --- draw corners --- */ t = ((c & (MZ_WEST|MZ_SOUTH)) | (cs & MZ_WEST) | (cw & MZ_SOUTH)); XSetForeground(display, gc, (t) ? black : white); XDrawPoint(display, window, gc, x-1, y+1); t = ((c & (MZ_EAST|MZ_SOUTH)) | (cs & MZ_EAST) | (ce & MZ_SOUTH)); XSetForeground(display, gc, (t) ? black : white); XDrawPoint(display, window, gc, x+FIELDWD-1, y+1); t = ((c & (MZ_EAST|MZ_NORTH)) | (cn & MZ_EAST) | (ce & MZ_NORTH)); XSetForeground(display, gc, (t) ? black : white); XDrawPoint(display, window, gc, x+FIELDWD-1, y-FIELDWD+1); t = ((c & (MZ_WEST|MZ_NORTH)) | (cn & MZ_WEST) | (cw & MZ_NORTH)); XSetForeground(display, gc, (t) ? black : white); XDrawPoint(display, window, gc, x-1, y-FIELDWD+1); /* --- draw walls --- */ XSetForeground(display, gc, (c & MZ_SOUTH) ? black : white); XDrawLine(display, window, gc, x, y+1, x+FIELDWD-2, y+1); XSetForeground(display, gc, (c & MZ_EAST) ? black : white); XDrawLine(display, window, gc, x+FIELDWD-1, y, x+FIELDWD-1, y-FIELDWD+2); XSetForeground(display, gc, (c & MZ_NORTH) ? black : white); XDrawLine(display, window, gc, x, y-FIELDWD+1, x+FIELDWD-2, y-FIELDWD+1); XSetForeground(display, gc, (c & MZ_WEST) ? black : white); XDrawLine(display, window, gc, x-1, y, x-1, y-FIELDWD+2); /* --- draw corn heap --- */ c &= MZ_ITEMS; /* get corn on the field */ if (c > 0) { /* if there is corn on the field */ if (c > 12) c = 12; /* limit heap size */ t = (c >> 1) +(c & 1); /* calculate circle */ c = (c >> 1); /* extensions */ x += (FIELDWD/2)-1 -t; /* compute coordinates and width */ y -= (FIELDWD/2)-1 +c; c += t; XSetForeground(display, gc, yellow); XFillArc(display, window, gc, x, y, c, c, 0, 360*64); XSetForeground(display, gc, orange); XDrawArc(display, window, gc, x, y, c, c, 0, 360*64); } /* draw corn heap */} /* draw_field() *//*--------------------------------------------------------------------*/static void hms_disp (HAMSTER *hms, int cmd, int arg){ /* --- hamster display function */ int id; /* hamster identifier */ int x, y, sx, sy; /* coordinates of hamster */ int dir; /* direction of hamster */ SPRITE *sprite; /* sprite to control */ int cnt; /* number of steps to move */ int series; /* sprite image series */ if (appdata.speed >= MAXSPEED) return; /* if maximal speed set, abort */ id = hms_id(hms); /* get hamster identifier */ sprite = hmscb[id].sprite; /* and associated sprite */ switch (cmd) { /* evaluate command */ case HMS_CREATED: /* --- if hamster was created */ mz_getpos(maze, &sx, &sy);/* get start position and */ hms_pos(hms, &x, &y); /* current position of hamster */ x += sx; y += sy; /* and compute absolute position */ x = xoff +x *FIELDWD +(FIELDWD-SPRITEWD)/2; y = yoff -y *FIELDWD -(FIELDWD-SPRITEWD)/2 -SPRITEWD +1; dir = hms_dir(hms); /* get direction (line of sight) */ switch (dir) { /* evaluate direction */ case HMS_EAST : series = 0; break; case HMS_NORTH: series = 1; break; case HMS_WEST : series = 2; break; case HMS_SOUTH: series = 3; break; default : return; /* get sprite image series number */ } spr_select(sprite, series, 0); spr_draw(sprite, x, y); /* select and draw sprite image */ case HMS_SCORED: /* --- if score has changed */ sprintf(buf, "%d", hms_score(hms)); mn_info(menu, buf); break; /* set new score */ case HMS_MOVED: /* --- if hamster was moved */ dir = hms_dir(hms); /* get direction (line of sight) */ switch (dir) { /* and evaluate it */ case HMS_EAST : x = 2; y = 0; cnt = FIELDWD/2; break; case HMS_NORTH: x = 0; y = -2; cnt = FIELDWD/2; break; case HMS_WEST : x = -2; y = 0; cnt = FIELDWD/2; break; case HMS_SOUTH: x = 0; y = 2; cnt = FIELDWD/2; break; default : return; /* get offsets to new field */ } if (appdata.speed >= 16) { x *= 8; y *= 8; cnt /= 8; } else if (appdata.speed >= 8) { x *= 4; y *= 4; cnt /= 4; } else if (appdata.speed >= 4) { x *= 2; y *= 2; cnt /= 2; } x = spr_move(sprite, x, y, 0, cnt, 1.0F/cnt/appdata.speed, reply, 0); break; /* move sprite */ case HMS_TURNED: /* --- if hamster was turned */ dir = hms_dir(hms); /* get direction (line of sight) */ switch (dir) { /* and evaluate it */ case HMS_EAST : series = (arg == HMS_POS) ? 3 : 5; break; case HMS_NORTH: series = (arg == HMS_POS) ? 0 : 6; break; case HMS_WEST : series = (arg == HMS_POS) ? 1 : 7; break; case HMS_SOUTH: series = (arg == HMS_POS) ? 2 : 4; break; default : return; /* get sprite image series number */ } /* and select image series */ if (appdata.speed >= 50) {/* if not to show turns */ spr_select(sprite, series, 6); return; /* simply select the last image */ } /* and abort the function */ spr_select(sprite, series, 0); /* select image series */ if (appdata.speed >= 16) { x = 6; cnt = 1; } else if (appdata.speed >= 4) { x = 3; cnt = 2; } else { x = 1; cnt = 6; } spr_move(sprite, 0, 0, x, cnt, 1.0F/cnt/appdata.speed, reply, 0); break; /* turn sprite */ case HMS_FIELD: /* --- if field contents has changed */ mz_getpos(maze, &sx, &sy);/* get start position and */ hms_pos(hms, &x, &y); /* current position of hamster */ x += sx; y += sy; /* and compute absolute position */ spr_undraw(sprite); /* undraw sprite */ draw_field(x, y); /* update changed field */ spr_draw(sprite, INT_MIN, INT_MIN); break; /* redraw sprite */ case HMS_DELETED: /* --- if hamster was deleted */ spr_undraw(sprite); break;/* undraw sprite */ default: break; /* ignore everything else */ } XFlush(display); /* flush buffered drawing commands */} /* hms_disp() *//*--------------------------------------------------------------------*/static void resize (Dimension width, Dimension height){ /* --- resize widgets */ Dimension w, h; /* width and height of top widget */ width *= FIELDWD; height *= FIELDWD; xoff = 0; yoff = height-2; /* compute extensions and set offsets */ w = mn_minwidth(menu) -1; /* get minimal width of maze widget */ if (w > width) width = w; /* compute the maze viewport width */ h = mn_height(menu) +height; XtVaSetValues(w_top, XtNwidth, width+1, XtNheight, h+1, XtNmaxWidth, width+1, XtNmaxHeight, h+1, NULL); XtVaSetValues(w_maze, XtNwidth, width-1, XtNheight, height-1, NULL); XtVaSetValues(w_view, XtNwidth, width-1, XtNheight, height-1, NULL); mn_resize(menu, width-1); /* set new widget extensions */} /* resize() *//*---------------------------------------------------------------------- Dialog Box Callback Functions----------------------------------------------------------------------*/static void dcb_load (Widget widget, XtPointer ok, XtPointer fname){ /* --- 'Load Maze...' callback */ int i = FN_MAX -1; /* loop variable */ char *src, *dst; /* to traverse file names */ FILE *file; /* file to read from */ MAZE *tmp; /* temporary buffer for loaded maze */ mn_enable(menu, MN_MENU, 1); /* enable menu bar */ if (!ok) return; /* if 'cancel' button pressed, abort */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -