📄 whamster.c
字号:
/*---------------------------------------------------------------------- File : whamster.c Contents: main program for hamster (Windows 95 version) Author : Christian Borgelt History : 14.10.1997 file created 16.10.1997 first version completed 20.10.1997 multithread version finished 31.10.1997 minor improvements 21.12.1997 two process version programming started 03.01.1997 first two process version completed 16.01.1998 constant MAXHEAP defined as HMS_MAXCORN 26.01.1998 calls to AllocConsole and FreeConsole added 12.06.1998 minor improvements 16.06.1998 menu item `Reload Maze...' added----------------------------------------------------------------------*/#define select SELECT /* just to fool Window's includes */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <ctype.h>#include <math.h>#include <time.h>#include <windows.h>#undef select#include "maze.h"#include "server.h"#include "sprite.h"#include "whamster.rh"/*---------------------------------------------------------------------- Preprocessor Definitions----------------------------------------------------------------------*/#define PRGNAME "whamster"#define NONAME "<noname>"/* --- abbreviations --- */#define HINST HINSTANCE#define MKIRSC MAKEINTRESOURCE#define WINSTYLE WS_TILED|WS_CAPTION|WS_SYSMENU|WS_BORDER#define WHITE RGB(0xff, 0xff, 0xff)#define BLACK RGB(0x00, 0x00, 0x00)#define PATH_MAX _MAX_PATH/* --- edit box functions --- */#define edt_set(h,i,s) SetDlgItemText(h, i, s)#define edt_get(h,i,s,n) GetDlgItemText(h, i, s, n)#define int_set(h,i,n) SetDlgItemInt(h, i, n, 0)#define int_get(h,i) GetDlgItemInt(h, i, NULL, 0)/* --- check box functions --- */#define chk_set(h,i,s) CheckDlgButton(h, i, s)#define chk_get(h,i) IsDlgButtonChecked(h, i)/* --- extensions and values --- */#define HMS_MINXEXT 8 /* minimal x-extension of maze */#define HMS_MINYEXT 1 /* minimal y-extension of maze */#define MAXHEAP HMS_MAXCORN /* maximal size of corn heap */#define MINSPEED 0.1F /* minimal hamster speed */#define MAXSPEED 100.0F /* maximal hamster speed */#define FIELDWD 16 /* width of displayed field (pixels) */#define SPRITEWD 13 /* width of hamster sprite (pixels) */#define BDPENALTY 1000 /* penalty for program breakdown *//* --- flags --- */#define MZ_LOAD 0 /* load a maze */#define MZ_SAVE 1 /* save a maze */#define MZ_NEW 2 /* get a new file name *//* --- error codes --- */#define OK 0 /* no error */#define E_NONE 0 /* no error */#define E_NOMEM -1 /* not enough memory */#define E_FOPEN -2 /* cannot open file */#define E_FREAD -3 /* read error on file */#define E_FWRITE -4 /* write error on file */#define E_POPEN -5 /* cannot open pipe */#define E_PREAD -6 /* read error on pipe */#define E_PWRITE -7 /* write error on pipe */#define E_PBROKEN -8 /* broken pipe */#define E_PROCESS -9 /* cannot start process */#define E_THREAD -10 /* cannot start thread */#define E_UNKNOWN -11 /* unknown error *//*---------------------------------------------------------------------- Type Definitions----------------------------------------------------------------------*/typedef struct { /* --- application specific data */ int xext, yext; /* maze extensions */ float wallprob; /* wall probability */ int total; /* total corn in maze */ int maxheap; /* maximal size of corn heap */ float speed; /* hamster speed (fields/second) */ int corncnt; /* collected corn */ int movecnt; /* number of moves made */ int crshcnt; /* number of crashes against walls */ int score; /* score achieved */ char fn_maze[PATH_MAX +256]; /* file name of current maze */ char fn_hms [PATH_MAX +256]; /* file name of executable */} AppData; /* (application specific data) */typedef struct { /* --- hamster control block --- */ HAMSTER *hamster; /* hamster to control */ SPRITE *sprite; /* sprite associated with hamster */} HMSCB; /* (hamster control block) *//*---------------------------------------------------------------------- Constants----------------------------------------------------------------------*/const char *errmsgs[] = { /* error messages */ /* E_NONE 0 */ "no error", /* E_NOMEM -1 */ "not enough memory", /* E_FOPEN -2 */ "cannot open file\n%s", /* E_FREAD -3 */ "read error on file\n%s", /* E_FWRITE -4 */ "write error on file\n%s", /* E_POPEN -5 */ "cannot open pipe", /* E_PREAD -6 */ "read error on pipe", /* E_PWRITE -7 */ "write error on pipe", /* E_PBROKEN -8 */ "broken pipe", /* E_PROCESS -9 */ "cannot start child process\n%s", /* E_THREAD -10 */ "cannot start pipe thread", /* E_UNKNOWN -11 */ "unknown error"};/*---------------------------------------------------------------------- Global Variables----------------------------------------------------------------------*/static AppData appdata = { /* application specific data */ 20, 15, /* initial maze extensions */ 0.75F, 500, 8, /* wall prob., total corn, max. heap */ 2.5F, /* inital hamster speed */ 0, 0, 0, 0, /* score variables */ NONAME, /* file name of current maze */ "chamster.exe" }; /* file name of executable */static HINST hinst; /* instance handle */static HWND hmain; /* handle of main window */static char buf[PATH_MAX +1024]; /* message buffer *//* --- brushes --- */static HBRUSH br_white; /* white brush (to draw background) */static HBRUSH br_grey; /* grey brush (to draw home field) */static HBRUSH br_yellow; /* yellow brush (to draw corn) *//* --- pens --- */static HPEN pen_white; /* white pen (to draw background) */static HPEN pen_black; /* black pen (to draw walls) */static HPEN pen_orange; /* orange pen (to draw corn) *//* --- child process and pipe variables --- */static HANDLE process = NULL; /* handle of hamster process */static HANDLE thread = NULL; /* handle of pipe input thread */static HANDLE p_in = NULL; /* input pipe (child -> parent) */static HANDLE p_out = NULL; /* output pipe (parent -> child) *//* --- hamster variables --- */static HBITMAP hms_bmap; /* handle of sprite bitmap */static HBITMAP hms_mask; /* handle of mask bitmap */static MAZE *maze; /* maze the hamster is in */static HMSCB hmscb[1] = { /* hamster control blocks */ { NULL, NULL } }; /* (at most one hamster) */static int xoff, yoff; /* offsets for drawing */ /*---------------------------------------------------------------------- Auxiliary Functions----------------------------------------------------------------------*/static void error (int code, ...){ /* --- print error message */ va_list args; /* list of variable arguments */ const char *msg; /* error message */ if ((code > 0) || (code < E_UNKNOWN)) code = E_UNKNOWN; /* check error code */ va_start(args, code); /* get variable arguments */ msg = errmsgs[-code]; /* and error message text */ if (!msg) msg = errmsgs[-E_UNKNOWN]; vsprintf(buf, msg, args); /* format error message */ MessageBox(hmain, buf, PRGNAME, MB_OK|MB_ICONSTOP); va_end(args); /* show alert dialog box */} /* error() *//*--------------------------------------------------------------------*/static double drand (void){ /* --- compute random number in [0,1) */ return rand() /(RAND_MAX +1.0);} /* drand() *//*---------------------------------------------------------------------- Drawing Functions----------------------------------------------------------------------*/static void draw_field (HDC hdc, int x, int y){ /* --- draw maze field */ RECT rc; /* field rectangle */ 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 --- */ rc.left = x; rc.right = x +FIELDWD -1; rc.bottom = y; rc.top = y -FIELDWD +1; FillRect(hdc, &rc, (c & MZ_HOME) ? br_grey : br_white); /* --- draw corners --- */ t = ((c & (MZ_WEST|MZ_SOUTH)) | (cs & MZ_WEST) | (cw & MZ_SOUTH)); SetPixel(hdc, x -1, y, (t) ? BLACK : WHITE); t = ((c & (MZ_EAST|MZ_SOUTH)) | (cs & MZ_EAST) | (ce & MZ_SOUTH)); SetPixel(hdc, x +FIELDWD-1, y, (t) ? BLACK : WHITE); t = ((c & (MZ_EAST|MZ_NORTH)) | (cn & MZ_EAST) | (ce & MZ_NORTH)); SetPixel(hdc, x +FIELDWD-1, y -FIELDWD, (t) ? BLACK : WHITE); t = ((c & (MZ_WEST|MZ_NORTH)) | (cn & MZ_WEST) | (cw & MZ_NORTH)); SetPixel(hdc, x -1, y -FIELDWD, (t) ? BLACK : WHITE); /* --- draw walls --- */ SelectObject(hdc, (c & MZ_SOUTH) ? pen_black : pen_white); MoveToEx(hdc, x, y, NULL); LineTo (hdc, x +FIELDWD-1, y); SelectObject(hdc, (c & MZ_EAST) ? pen_black : pen_white); MoveToEx(hdc, x +FIELDWD-1, y -1, NULL); LineTo (hdc, x +FIELDWD-1, y -FIELDWD); SelectObject(hdc, (c & MZ_NORTH) ? pen_black : pen_white); MoveToEx(hdc, x, y -FIELDWD, NULL); LineTo (hdc, x +FIELDWD-1, y -FIELDWD); SelectObject(hdc, (c & MZ_WEST) ? pen_black : pen_white); MoveToEx(hdc, x -1, y -1, NULL); LineTo (hdc, x -1, y -FIELDWD); /* --- draw corn heap --- */ c &= MZ_ITEMS; /* get size of corn heap */ if (c > 0) { /* if there is corn on the field */ if (c > 12) c = 12; /* limit heap size */ t = (c >> 1) +(c & 1); /* calculate ellipse */ c = (c >> 1) +1; /* extensions */ SelectObject(hdc, pen_orange); /* get orange pen */ SelectObject(hdc, br_yellow); /* and yellow brush */ Ellipse(hdc, x +(FIELDWD/2)-1 -t, y -(FIELDWD/2) -t, x +(FIELDWD/2)-1 +c, y -(FIELDWD/2) +c); } /* draw corn heap */} /* draw_field() *//*--------------------------------------------------------------------*/static void hms_disp (HAMSTER *hms, int cmd, int arg){ /* --- hamster display function */ HDC hdc; /* handle of device context */ 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; dir = hms_dir(hms); /* get direction (line of sight) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -