📄 whamster.c
字号:
if (!file) { error(E_FOPEN, fname); return -1; } if (mz_save(maze, file) != 0) error(E_FWRITE, fname); fclose(file); /* save maze and close file */ strcpy(appdata.fn_maze, fname); } /* note name of maze */ else { /* if to load a maze */ file = fopen(fname, "r"); /* open selected file */ if (!file) { error(E_FOPEN, fname); return -1; } tmp = mz_load(file); /* try to load maze */ fclose(file); /* and close input file */ if (!tmp) { error(E_FREAD, fname); return -1; } mz_delete(maze); maze = tmp;/* delete old maze */ mz_exts(maze, &appdata.xext, &appdata.yext); strcpy(appdata.fn_maze, fname); } /* note size and name of maze */ return 0; /* return 'ok' */} /* mz_file() *//*--------------------------------------------------------------------*/static int select (void){ /* --- select a hamster program */ static char fname[_MAX_PATH+1]; /* file name */ static char path [_MAX_PATH+1]; /* and path */ static char filter[] = /* file selection filter */ "hamster (*.exe)\0*.exe\0" /* hamsters */ "all files (*.*)\0*.*\0"; /* all files */ static OPENFILENAME ofn = { /* file selector structure */ sizeof(OPENFILENAME), /* lStructSize */ NULL, NULL, /* hwndOwner, hInstance */ filter, NULL, /* lpstrFilter, lpstrCustomFilter */ 0, 1, /* nMaxCustFilter, nFilterIndex */ fname, _MAX_PATH, /* lpstrFile, nMaxFile */ NULL, _MAX_FNAME+_MAX_EXT, /* lpstrFileTitle, nMaxFileTitle */ path, /* lpstrInitialDir */ "Select Hamster Program", /* lpstrTitle */ OFN_FILEMUSTEXIST, 0, 0, /* Flags, nFileOffset, nFileExtension */ "exe", 0L, /* lpstrDefExt, lCustData */ NULL, NULL }; /* lpfnHook, lpTemplateName */ ofn.hwndOwner = hmain; /* set window handle */ if (GetOpenFileName(&ofn) == 0) return -1; /* open file selector box */ strcpy(appdata.fn_hms, fname);/* copy name of hamster program */ return 0; /* return 'ok' */} /* select() *//*---------------------------------------------------------------------- Process and Thread Functions----------------------------------------------------------------------*/static void mn_enable (int enable){ /* --- enable/disable menu items */ HMENU menu; /* handle of window menu */ MENUITEMINFO mii; /* for menu customization */ UINT flag; /* enable/disable flag */ menu = GetMenu(hmain); /* get menu handle */ flag = (enable) ? MF_ENABLED : MF_GRAYED; EnableMenuItem(menu, MI_RELOAD, flag);
EnableMenuItem(menu, MI_LOAD, flag); /* enable/disable those */ EnableMenuItem(menu, MI_SAVE, flag); /* menu items that should */ EnableMenuItem(menu, MI_SAVEAS, flag); /* not be selected while */
EnableMenuItem(menu, MI_SELECT, flag); /* a hamster is running */ EnableMenuItem(menu, MI_SIZE, flag); EnableMenuItem(menu, MI_CLEAR, flag); EnableMenuItem(menu, MI_RANDOM, flag); mii.cbSize = sizeof(MENUITEMINFO); /* set either the */ mii.fMask = MIIM_ID|MIIM_TYPE; /* 'Start Hamster...' or */ mii.fType = MFT_STRING; /* 'Stop Hamster...' item */ mii.wID = (enable) ? MI_START : MI_STOP; LoadString(hinst, (enable) ? CS_START : CS_STOP, buf, 80); mii.dwTypeData = buf; mii.cch = strlen(buf); SetMenuItemInfo(menu, (enable) ? MI_STOP : MI_START, FALSE, &mii);} /* mn_enable() *//*--------------------------------------------------------------------*/static void stop (int inthread, int errcode){ /* --- stop hamster thread */ HAMSTER *hamster; /* the hamster and */ SPRITE *sprite; /* its associated sprite */ mn_enable(1); /* enable/change menu items */ /* --- stop process and thread --- */ if (p_in) { CloseHandle(p_in); p_in = NULL; } if (p_out) { CloseHandle(p_out); p_out = NULL; } if (process) { /* if the hamster is running, */ TerminateProcess(process, 0); /* terminate the process */ if (!inthread) { /* if called from main program */ TerminateThread(thread, 0); thread = NULL; } } /* terminate thread and delete it */ if (errcode != E_NONE) /* show alert dialog box */ error(errcode, appdata.fn_hms); if (!process) return; /* if there is no process, abort */ process = NULL; /* delete the hamster process */ /* --- clean up and show result --- */ hamster = hmscb[0].hamster; /* get hamster */ if (!hamster) { /* if no hamster exists, clear score */ appdata.corncnt = appdata.movecnt = 0; appdata.crshcnt = appdata.score = 0; } else { /* if a hamster exists */ appdata.corncnt = hms_corncnt(hamster); appdata.movecnt = hms_movecnt(hamster); appdata.crshcnt = hms_crshcnt(hamster); appdata.score = hms_score(hamster); hms_delete(hamster); hmscb[0].hamster = NULL; } /* note score and delete hamster */ sprite = hmscb[0].sprite; /* get hamster sprite */ if (sprite) { /* if a sprite exists, */ spr_undraw(sprite); /* undraw sprite */ spr_delete(sprite, 0); hmscb[0].sprite = NULL; } /* delete sprite */ DialogBox(hinst, MKIRSC(DB_RESULT), hmain, dp_result); if (appdata.speed >= MAXSPEED) /* if run without display, */ InvalidateRect(hmain, NULL, 0); /* redraw window */ SetWindowText(hmain, PRGNAME); /* reset window title */ if (inthread) ExitThread(0); /* terminate thread */} /* stop() *//*--------------------------------------------------------------------*/static int readarg (int *arg){ /* --- read argument from pipe */ char c; /* character read */ DWORD cnt; /* number of bytes read */ int sign = 0; /* sign of the argument */ int state = 0; /* state of automaton */ *arg = 0; /* initialize argument */ while (1) { /* read next character */ if (!ReadFile(p_in, &c, 1, &cnt, NULL)) stop(1, E_PREAD); if (cnt <= 0) stop(1, E_PBROKEN); switch (state) { /* evaluate state of automaton */ case 0: /* --- skip blanks */ if ((c == '\r') || (c == '\n')) return -1; else if (c == '+') { state = 1; } else if (c == '-') { sign = -1; state = 1; } else if (isdigit(c)) { *arg = c -'0'; state = 2; } else if (!isspace(c)) stop(1, E_PREAD); break; /* evaluate the character read */ case 1: /* --- sign (+/-) read */ if (!isdigit(c)) stop(1, E_PREAD); *arg = c -'0'; state = 2; /* check for a digit and */ break; /* continue with state 2 */ case 2: /* --- at least one digit read */ if (isdigit(c)) *arg = *arg *10 +(c -'0'); else if (!isspace(c)) stop(1, E_PREAD); else { /* if end of argument reached */ if (sign < 0) *arg = -*arg; return ((c == '\r') || (c == '\n')) ? 1 : 0; } break; /* set argument value and */ } /* return end of line indicator */ } /* while (1) .. */} /* readarg() *//*----------------------------------------------------------------------The above function is necessary to read the command arguments from thepipe. A redirection of the standard input (with SetStdHandle) does notwork, since it does not have any effect on the `scanf' function (forsome unknown reason --- it works fine for the child process). Checkingfor a broken pipe by testing the value of `cnt' (as done above) doesnot work, too, since the read remains blocked if the connected processis killed (in contrast to UNIX, where killing a process causes an endof file state of all pipes connected to it).----------------------------------------------------------------------*/static DWORD ip_pipe (LPDWORD dummy){ /* --- pipe input procedure */ static char buf[96]; /* write buffer */ HAMSTER *hamster; /* hamster to control */ char cmd; /* command read */ int id = 0; /* hamster identifier */ int arg; /* command argument */ int x, y; /* hamster position */ DWORD cnt; /* number of read/written chars */ while (1) { /* pipe input loop */ /* --- read command from pipe --- */ do { /* read next character */ if (!ReadFile(p_in, &cmd, 1, &cnt, NULL)) stop(1, E_PREAD); if (cnt <= 0) stop(1, E_PBROKEN); } while (isspace(cmd)); /* until command read */ /* --- read command argument(s) from pipe --- */ switch (cmd) { /* read command arguments */ case 'c': /* --- create hamster */ if (readarg(&arg) >= 0) stop(1, E_PREAD); break; /* no arguments */ case 'd': case 'm': /* --- delete and move hamster */ if (readarg(&id) != 1) stop(1, E_PREAD); break; /* one argument: hamster id */ case 't': case 'l': /* --- turn hamster and load */ if ((readarg(&id) != 0) || (readarg(&arg) != 1)) stop(1, E_UNKNOWN); /* two arguments: hamster id */ break; /* and direction/amount */ default: /* --- unknown command */ stop(1, E_PREAD); return 0; } /* stop execution */ /* --- evaluate command --- */ hamster = hmscb[id].hamster;/* get hamster to control */ switch (cmd) { /* evaluate command read */ case 'c': /* --- create hamster */ if (hamster) { /* if a hamster already exists, */ strcpy(buf, "c -1\n"); break; } /* deny request */ hmscb[0].sprite = /* create a sprite */ spr_create(hmain, SPRITEWD, SPRITEWD, hms_bmap, hms_mask); if (!hmscb[0].sprite) stop(1, E_NOMEM); hmscb[0].hamster = /* create a hamster */ hamster = hms_create(maze, 0, HMS_EAST, hms_disp); if (!hamster) stop(1, E_NOMEM); hms_pos(hamster,&x,&y); /* get hamster position */ sprintf(buf, "c %d %d %d %d %d %d %d\n", hms_id(hamster), x, y, hms_dir(hamster), hms_look(hamster), hms_corn(hamster), hms_load(hamster)); break; /* send hamster data */ case 'd': /* --- delete hamster */ strcpy(buf, "d 0\n"); /* echo delete command */ WriteFile(p_out, buf, strlen(buf), &cnt, NULL); FlushFileBuffers(p_out); stop(1, OK); return 0; /* stop hamster process */ case 'm': /* --- move hamster */ hms_move(hamster); /* move hamster forward */ hms_pos(hamster,&x,&y); /* and get new position */ sprintf(buf, "m %d %d %d %d %d\n", hms_id(hamster), x, y, hms_look(hamster), hms_corn(hamster)); break; /* send new hamster data */ case 't': /* --- turn hamster */ hms_turn(hamster, arg); /* turn hamster around */ sprintf(buf, "t %d %d %d\n", hms_id(hamster), hms_dir(hamster), hms_look(hamster)); break; /* send new hamster data */ case 'l': /* --- take/drop corn */ hms_take(hamster, arg); /* take/drop some corn */ sprintf(buf, "l %d %d %d\n", hms_id(hamster), hms_corn(hamster), hms_load(hamster)); break; /* send new hamster data */ default: /* --- unknown command */ stop(1, E_PREAD); return 0; /* stop execution */ } if (!WriteFile(p_out, buf, strlen(buf), &cnt, NULL)) stop(1, E_PWRITE); /* write reply to command to pipe */ } /* while (1) .. */} /* ip_pipe() *//*--------------------------------------------------------------------*/static void start (void){ /* --- start hamster process */ SECURITY_ATTRIBUTES sa; /* security attributes */ PROCESS_INFORMATION pi; /* process information */ STARTUPINFO si; /* startup information */ HANDLE c_in, c_out; /* child ends of pipes */ DWORD id; /* thread identifier */ int ok; /* flag for success */ if (process) return; /* if hamster is running, abort */ mn_enable(0); /* disable/change menu items */ /* --- create pipes --- */ sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; /* initialize security */ sa.lpSecurityDescriptor = NULL; /* attributes structure */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -