/* yamsweeper : Yet Another Mine Sweeper * * Copyright (C) 1992, 1993, 1994 by Hirofumi Yamamoto * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of the author not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. The author makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * Programmed by hirofumi@info.kawasaki-steel.co.jp for original version. * */ #include #include #include #include #include #include #include #include #ifdef _TIME_H #include #endif #include #ifdef AIXV3 #include #endif static char rcsid[] = "$Id: win.c,v 1.50 1994/11/03 00:17:08 hirofumi Rel hirofumi $"; #include "gentype.h" #include "struct.h" #include "funcs.h" #include "highscore.h" #ifdef PROTOCOL_DEBUG #define P(x) x #else #define P(x) #endif #if NO_FD_SET typedef long fd_mask; #define NBBY 8 /* number of bits in a byte */ #define FD_SETSIZE 256 #define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */ #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) #define FD_ZERO(p) bzero((char *)(p), sizeof (*(p))) #endif Widget toplevel; Display *d; Window r, w; Window niko; Window dig; Window panelw; Window file; Window filepulldown; Window counterw; Window congraturation, bangwindow; #if HIGH_SCORE Window highscore; #endif static int _ = True; AppData appData; /*GC*/ GC gc; GC ank; /* (fore)appData.fg */ GC menugc; GC panelgc; GC nikogc; GC digitgc; GC conggc; GC banggc; #if HIGH_SCORE GC highscgc; #endif GC timegc; GC filepulldowngc; GC filepulldownbgc; GC countergc; XFontStruct *fs; int nikop = 0; int menuheight = 0; int pulldownmenuheight = 0; int ankascent = 0; time_t done = 0; time_t start = 0; #define cat(x,y) x##y #define xcat(x,y) cat(x,y) #define CG(x) xcat(xcat(cg,x),_bits) #define BMS 32 /* width and height of bitmaps */ #define MENU (menuheight+4) #define BASE (BMS+6+MENU) #define FILEMENU "File" #include "bmps.h" #define XS 64 /* max size */ #define YS 64 int xs = 8, ys = 8; int maxbomb = 10; EM_MODE mode = EM_Beginner; /* States of Buttons */ /* HIDDEN: simply not opened, * OPEN: simply opened, * QUESTION: not opened, but marked as question * BOMB: marked as bomb, of course not opened */ typedef enum { HIDDEN, OPEN, QUESTION, BOMB } Live; typedef enum { X_NONE, XXX, BANG } Xtype; struct FLD { Live live; /* keeps a current state, as panel */ int st; /* keeps a number of bombs around the panel */ /* if -1, panel itself is a bomb */ Xtype x; /* when a game is over ... */ } field[XS][YS]; extern void NewGame(VOID), Beginner(VOID), Intermidiate(VOID), Expert(VOID), Quit(VOID); struct { char* title; void (*func)(VOID); } menucontents[] = { "New", NewGame, "", NULL, "Beginner", Beginner, "Intermidiate", Intermidiate, "Expert", Expert, "", NULL, #if HIGH_SCORE "High Score", ShowHighScore, "", NULL, #endif "Quit", Quit, NULL, NULL }; int #ifdef __STDC__ myrandom(int n) #else myrandom(n) int n; #endif { #if HAS_RANDOM return random() % n; #else /* not has random() */ return rand() % n; #endif } void #ifdef __STDC__ round(int y, int x) #else round(y, x) int y, x; #endif { int xx, yy; for (xx = -1; xx <= 1; ++xx) { if (x + xx < 0 || x + xx >= xs) continue; for (yy = -1; yy <= 1; ++yy) { if (y + yy < 0 || y + yy >= ys) continue; if (field[y+yy][x+xx].st != -1) ++field[y+yy][x+xx].st; } } } void InitField(VOID) { int i; int x, y; #if 1 for (x = 0; x < xs; ++x) { for (y = 0; y < ys; ++y) { field[y][x].st = 0; field[y][x].live = HIDDEN; field[y][x].x = X_NONE; } } for (i = 0; i < maxbomb; ++i) { int x = myrandom(xs); int y = myrandom(ys); if (field[y][x].st == -1 || (y == 0 && (x == 0 || x == xs - 1)) || (y == ys - 1 && (x == 0 || x == xs - 1))) { --i; } else { field[y][x].st = -1; round(y, x); } } #else /* DEBUG */ #define DEBUGIN "field.in" FILE* fp = fopen(DEBUGIN, "rt"); printf("InitField entered\n"); if (fp == NULL) { perror(DEBUGIN); exit(1); } maxbomb = 0; for (y = 0; y < ys; ++y) { for (x = 0; x < xs; ++x) { field[y][x].st = 0; field[y][x].live = HIDDEN; field[y][x].x = X_NONE; } } for (y = 0; y < ys; ++y) { for (x = 0; x < xs; ++x) { int c = getc(fp); while (c <= ' ') c = getc(fp); if (c == 'x') { field[y][x].st = -1; ++maxbomb; round(y, x); } } } fclose(fp); printf("InitField finished\n"); #endif } int cursorLevel = 0; Cursor cursorWait = 0; Cursor cursorNormal = 0; void WaitCursor(VOID) { if (cursorLevel++ == 0) { XDefineCursor(d, w, cursorWait); } } void TildeWaitCursor(VOID) { if (--cursorLevel <= 0) { cursorLevel = 0; XDefineCursor(d, w, cursorNormal); } } void ArrangeWindow(VOID) { XSizeHints* hints; long dmy; hints = XAllocSizeHints(); hints->width = hints->min_width = hints->max_width = BMS*xs; hints->height = hints->min_height = hints->max_height = BMS*ys+BASE; hints->flags = PSize | PMinSize | PMaxSize; XSetWMNormalHints(d, w, hints); XResizeWindow(d, w, BMS*xs, BMS*ys + BASE); XResizeWindow(d, panelw, BMS*xs, BMS*ys); XMoveWindow(d, niko, BMS*xs/2-BMS/2, MENU+2); XMoveWindow(d, counterw, BMS*xs - 4 - BMS/2*3, MENU+2); XFree(hints); } void #ifdef __STDC__ GlobalInit(Widget toplevel) #else GlobalInit(toplevel) Widget toplevel; #endif { int i; XSetWindowAttributes at; d = XtDisplay(toplevel); r = RootWindowOfScreen(XtScreen(toplevel)); fs = XQueryFont(d, appData.ank); menuheight= fs->max_bounds.ascent + fs->max_bounds.descent + 2; ankascent= fs->ascent; w = XCreateSimpleWindow(d, r, 100, 100, BMS*xs, BMS*xs, 2, appData.fg, appData.bg); counterw = XCreateSimpleWindow(d, w, 4, MENU+2, BMS/2*3, BMS, 1, appData.fg, appData.bg); XSelectInput(d, counterw, ExposureMask); niko = XCreateSimpleWindow(d, w, BMS*xs/2-BMS/2, MENU+2, BMS, BMS, 1, appData.fg, appData.bg); dig = XCreateSimpleWindow(d, w, 4, MENU+2, BMS/2*3, BMS, 1, appData.fg, appData.bg); panelw = XCreateSimpleWindow(d, w, 0, BASE, BMS*xs, BMS*ys, 1, appData.fg, appData.bg); XSelectInput(d, w, ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); XSelectInput(d, panelw, ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); XSelectInput(d, niko, ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); XSelectInput(d, dig, ExposureMask); ArrangeWindow(); XMapWindow(d, w); XMapWindow(d, niko); XMapWindow(d, dig); XMapWindow(d, panelw); XMapWindow(d, counterw); XStoreName(d, w, appData.name); congraturation = XCreateSimpleWindow(d, r, 20, BASE+20, 400, 100, 5, appData.fg, appData.bg); XSelectInput(d, congraturation, ExposureMask | ButtonPressMask | ButtonReleaseMask); XStoreName(d, congraturation, "results"); bangwindow = XCreateSimpleWindow(d, r, 20, BASE+20, 400, 100, 5, appData.fg, appData.bg); XSelectInput(d, bangwindow, ExposureMask | ButtonPressMask | ButtonReleaseMask); XStoreName(d, bangwindow, "results"); #if HIGH_SCORE highscore = XCreateSimpleWindow(d, r, 20, BASE+20, 400, 100, 5, appData.fg, appData.bg); XSelectInput(d, highscore, ExposureMask | ButtonPressMask | ButtonReleaseMask); XStoreName(d, highscore, "High Score"); #endif ank = XCreateGC(d, w, 0, 0); XSetFont(d, ank, appData.ank); XSetForeground(d, ank, appData.fg); XSetBackground(d, ank, appData.bg); countergc = XCreateGC(d, counterw, 0, 0); XSetFont(d, countergc, appData.ank); XSetForeground(d, countergc, appData.fg); XSetBackground(d, countergc, appData.bg); XSetGraphicsExposures(d, countergc, False); panelgc = XCreateGC(d, panelw, 0, 0); XSetFont(d, panelgc, appData.ank); XSetForeground(d, panelgc, appData.fg); XSetBackground(d, panelgc, appData.bg); XSetGraphicsExposures(d, panelgc, False); gc = XCreateGC(d, w, 0, 0); XSetForeground(d, gc, appData.fg); conggc = XCreateGC(d, congraturation, 0, 0); XSetFont(d, conggc, appData.ank); XSetForeground(d, conggc, appData.fg); XSetBackground(d, conggc, appData.bg); banggc = XCreateGC(d, bangwindow, 0, 0); XSetFont(d, banggc, appData.ank); XSetForeground(d, banggc, appData.fg); XSetBackground(d, banggc, appData.bg); #if HIGH_SCORE /* create High Score window's gc */ highscgc = XCreateGC(d, highscore, 0, 0); XSetFont(d, highscgc, appData.ank); XSetForeground(d, highscgc, appData.fg); XSetBackground(d, highscgc, appData.bg); #endif nikogc = XCreateGC(d, niko, 0, 0); XSetForeground(d, nikogc, appData.fg); XSetBackground(d, nikogc, appData.bg); digitgc = XCreateGC(d, dig, 0, 0); XSetForeground(d, digitgc, appData.bg); XSetBackground(d, digitgc, appData.fg); InitField(); InitBmps(); /* in bmps.c */ file = XCreateSimpleWindow(d, w, 4, 2, XTextWidth(fs, FILEMENU, sizeof(FILEMENU)-1), menuheight, 0, appData.fg, appData.bg); XSelectInput(d, file, ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); menugc = XCreateGC(d, file, 0, 0); XSetFont(d, menugc, appData.ank); XSetForeground(d, menugc, appData.fg); XSetBackground(d, menugc, appData.bg); XMapWindow(d, file); filepulldown = XCreateSimpleWindow(d, w, 4, menuheight-2, 120, 200, 2, appData.fg, appData.bg); XSelectInput(d, filepulldown, ExposureMask); XResizeWindow(d, filepulldown, 120, pulldownmenuheight = menuheight * (sizeOf(menucontents) - 1) + 4); at.save_under = True; XChangeWindowAttributes(d, filepulldown, CWSaveUnder, &at); filepulldowngc = XCreateGC(d, filepulldown, 0, 0); XSetFont(d, filepulldowngc, appData.ank); XSetForeground(d, filepulldowngc, appData.fg); XSetBackground(d, filepulldowngc, appData.bg); filepulldownbgc = XCreateGC(d, filepulldown, 0, 0); XSetFont(d, filepulldownbgc, appData.ank); XSetForeground(d, filepulldownbgc, appData.bg); XSetBackground(d, filepulldownbgc, appData.fg); cursorWait = XCreateFontCursor(d, XC_watch); cursorNormal = XCreateFontCursor(d, appData.cursor); XDefineCursor(d, w, cursorNormal); /* set menu cursor */ XDefineCursor(d, file, XCreateFontCursor(d, appData.menucursor)); } void ChangeColor(VOID) { } void UpdateDigit(VOID) { int x, y; int sum = 0; /* update left bombs */ for (x = 0; x < xs; ++x) { for (y = 0; y < ys; ++y) { if (field[y][x].live == BOMB) { ++sum; } } } sum = maxbomb - sum; if (sum > 999) sum = 999; else if (sum < -99) sum = -99; if (sum < 0) { sum = -sum; XCopyPlane(d, bmp_dminus, dig, digitgc, 0, 0, BMS/2, BMS, 0, 0, 1); } else { XCopyPlane(d, bmp_dcg[sum / 100 % 10], dig, digitgc, 0, 0, BMS/2, BMS, 0, 0, 1); } XCopyPlane(d, bmp_dcg[sum / 10 % 10], dig, digitgc, 0, 0, BMS/2, BMS, BMS/2, 0, 1); XCopyPlane(d, bmp_dcg[sum % 10], dig, digitgc, 0, 0, BMS/2, BMS, BMS/2*2, 0, 1); } void #ifdef __STDC__ UpdateCounter(int force) #else UpdateCounter(force) int force; #endif { int x, y; int current = time(NULL); int timee = current - start; static int last = 0; D(printf("UpdateCounter\n")); /* avoid continuous update */ if (last >= current && !force) { D(printf("avoided\n")); return; } last = current; if (start == 0) { timee = 0; } else if (done) { timee = done - start; } XCopyPlane(d, bmp_dcg[timee / 100 % 10], counterw, countergc, 0, 0, BMS/2, BMS, 0, 0, 1); XCopyPlane(d, bmp_dcg[timee / 10 % 10], counterw, countergc, 0, 0, BMS/2, BMS, BMS/2, 0, 1); XCopyPlane(d, bmp_dcg[timee % 10], counterw, countergc, 0, 0, BMS/2, BMS, BMS/2*2, 0, 1); } void #ifdef __STDC__ RedrawPanel(int x, int y) #else RedrawPanel(x, y) int x, y; #endif { Pixmap pix; if (field[y][x].x == XXX) { pix = bomb; } else if (field[y][x].x == BANG) { pix = bombout; } else if (field[y][x].live == HIDDEN) { pix = tile; } else if (field[y][x].live == QUESTION) { pix = question; } else if (field[y][x].live == BOMB) { pix = tilebomb; } else if (field[y][x].st == -1) { pix = bomb; } else { D(printf("(%d,%d)=%d ", x,y,field[y][x].st)); D(fflush(stdout)); if (field[y][x].st > 8 || field[y][x].st < 0) { fprintf(stderr, "ERROR\n"); exit(1); } if (field[y][x].st < 0 || field[y][x].st > 8) { D(printf("field[%d][%d].st=%d\n", y, x, field[y][x].st)); } pix = bits[field[y][x].st]; } XCopyPlane(d, pix, panelw, panelgc, 0, 0, BMS, BMS, x * BMS, y * BMS, 1); if (field[y][x].x == XXX) { XDrawLine(d, panelw, panelgc, x * BMS, y * BMS, (x + 1) * BMS, (y + 1) * BMS); XDrawLine(d, panelw, panelgc, x * BMS, (y + 1) * BMS, (x + 1) * BMS, y * BMS); } } void UpdateFile(VOID) { XDrawString(d, file, menugc, 0, ankascent, FILEMENU, sizeof(FILEMENU) - 1); } void RedrawMain(VOID) { XDrawLine(d, w, ank, 0, MENU, BMS*xs, MENU); } void RedrawNiko(VOID) { XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); } void #ifdef __STDC__ Redraw(XEvent* ev) #else Redraw(ev) XEvent* ev; #endif { int x, y; D(printf("Redraw()\n")); WaitCursor(); UpdateDigit(); UpdateCounter(True); UpdateFile(); RedrawNiko(); for (y = 0; y < ys; ++y) { for (x = 0; x < xs; ++x) { RedrawPanel(x, y); } } TildeWaitCursor(); } void RedrawResults(VOID) { #define CSTR "CONGRATURATIONS!!" #define DSTR "BA-----------NG!!" XDrawString(d, congraturation, conggc, 20, 40, CSTR, sizeof(CSTR) - 1); XDrawString(d, bangwindow, banggc, 20, 40, DSTR, sizeof(DSTR) - 1); } void #ifdef __STDC__ RedrawPanelWin(XEvent* ev) #else RedrawPanelWin(ev) XEvent* ev; #endif { XExposeEvent* exp = &ev->xexpose; /* (exp->x, exp->y) -> (exp->x + exp->width, exp->y + exp->height) */ int xst = exp->x / BMS; int yst = exp->y / BMS; int xen = exp->x + exp->width; int yen = exp->y + exp->height; int x, y; xen = xen / BMS + (xen % BMS != 0); yen = yen / BMS + (yen % BMS != 0); if (xen >= xs) xen = xs - 1; if (yen >= ys) yen = ys - 1; D(printf("(%d,%d)-(%d,%d)\n", xst, yst, xen, yen)); for (y = yst; y <= yen; ++y) { for (x = xst; x <= xen; ++x) { RedrawPanel(x, y); } } } void RedrawPulldown(VOID) { int i; int y = 2; for (i = 0; menucontents[i].title; ++i) { if (menucontents[i].title[0] == 0) { XDrawLine(d, filepulldown, filepulldowngc, 0, ankascent + menuheight * i, 400, ankascent + menuheight * i); } else { XDrawString(d, filepulldown, filepulldowngc, 4, ankascent + menuheight * i, menucontents[i].title, strlen(menucontents[i].title)); } } } void #ifdef __STDC__ RedrawEachParts(XEvent* ev) #else RedrawEachParts(ev) XEvent* ev; #endif { Window win = ev->xany.window; WaitCursor(); if (win == panelw) { RedrawPanelWin(ev); } else if (win == congraturation || win == bangwindow) { RedrawResults(); } #if HIGH_SCORE else if (win == highscore) { RedrawHighScore(); } #endif else if (win == counterw) { UpdateCounter(True); } else if (win == dig) { UpdateDigit(); } else if (win == niko) { RedrawNiko(); } else if (win == file) { UpdateFile(); } else if (win == filepulldown) { RedrawPulldown(); } else if (win == w) { if (ev->xexpose.count == 0) { RedrawMain(); } } TildeWaitCursor(); } void startCount(VOID) { time(&start); done = 0; LogUser("starts game"); } void stopCount(VOID) { time(&done); } /* KONOATARI */ void endGame(VOID) { LogUser("ends game"); stopCount(); } void NewGame(VOID) { start = 0; InitField(); nikop = 0; done = 0; XUnmapWindow(d, congraturation); XUnmapWindow(d, bangwindow); #if HIGH_SCORE XUnmapWindow(d, highscore); #endif Redraw(NULL); } void calcNumBomb(VOID) { maxbomb = xs * ys * 10 / 64; if (xs * ys > 256) { maxbomb *= 99; maxbomb /= 75; } } void assignSize(VOID) { xs = appData.mapSizeX; ys = appData.mapSizeY; if (xs > XS || ys > YS) { fprintf(stderr, "Map size too LARGE !\n"); exit(1); } if (xs == 8 && ys == 8) { mode = EM_Beginner; } else if (xs == 16 && ys == 16) { mode = EM_Intermidiate; } else if (xs == 30 && ys == 16) { mode = EM_Expert; } else { mode = EM_Other; } calcNumBomb(); } void Beginner(VOID) { xs = 8; ys = 8; calcNumBomb(); ArrangeWindow(); mode = EM_Beginner; NewGame(); } void Intermidiate(VOID) { xs = 16; ys = 16; calcNumBomb(); ArrangeWindow(); mode = EM_Intermidiate; NewGame(); } void Expert(VOID) { xs = 30; ys = 16; calcNumBomb(); ArrangeWindow(); mode = EM_Expert; NewGame(); } void Quit(VOID) { _ = False; } int map[YS][XS]; #define check(y,x) (x < 0 || y < 0 || x >= xs || y >= ys || field[y][x].st != -1) void #ifdef __STDC__ _lookaround(int y, int x) #else _lookaround(y, x) int y, x; #endif { if (y < 0 || y >= ys || x < 0 || x >= xs || map[y][x] || field[y][x].live != HIDDEN) return; map[y][x] = True; field[y][x].live = OPEN; RedrawPanel(x, y); if (check(y-1,x-1) && check(y-1,x) && check(y-1,x+1) && check(y,x-1) && check(y,x+1) && check(y+1,x-1) && check(y+1,x) && check(y+1,x+1)) { _lookaround(y-1,x-1); _lookaround(y-1,x); _lookaround(y-1,x+1); _lookaround(y,x-1); _lookaround(y,x+1); _lookaround(y+1,x-1); _lookaround(y+1,x); _lookaround(y+1,x+1); } } void #ifdef __STDC__ lookaround(int y, int x) #else lookaround(y, x) int y, x; #endif { int xx, yy; int open = 0; for (yy = 0; yy < ys; ++yy) { for (xx = 0; xx < xs; ++xx) { if (field[yy][xx].live != HIDDEN) { ++open; } } } if (open == 0) { D(printf("Started.\n")); startCount(); } memset((char*)map, 0, sizeof map); _lookaround(y, x); } Bool checkit(VOID) { int x, y; int opened = 0; for (y = 0; y < ys; ++y) { for (x = 0; x < xs; ++x) { switch (field[y][x].live) { case OPEN: ++opened; break; } } } if (opened == xs * ys - maxbomb) return True; return False; } void Congraturation(VOID) { int x, y; int i; for (x = 0; x < xs; ++x) { for (y = 0; y < ys; ++y) { switch (field[y][x].live) { case HIDDEN: field[y][x].live = BOMB; break; } } } nikop = 3; if (appData.dispResults) XMapWindow(d, congraturation); Redraw(NULL); endGame(); stopCount(); #if HIGH_SCORE check_highscore(); #endif } void Bomb(VOID) { int x, y; for (x = 0; x < xs; ++x) { for (y = 0; y < ys; ++y) { switch (field[y][x].live) { case BOMB: if (field[y][x].st != -1) { field[y][x].live = OPEN; field[y][x].x = XXX; } break; default: field[y][x].live = OPEN; break; } } } nikop = 1; Redraw(NULL); endGame(); stopCount(); } typedef struct { #ifdef __STDC__ void (*pressed)(XEvent*); void (*motion)(XEvent*); void (*released)(XEvent*); #else void (*pressed)(); void (*motion)(); void (*released)(); #endif } ButtonFunc; Window pressedWin; Boolean lastin; int pressx; int pressy; Boolean inmotion; extern ButtonFunc* funcs; extern ButtonFunc noneFuncs; int #ifdef __STDC__ checkround(int y, int x) #else checkround(y, x) int y, x; #endif { int xx, yy; int sum = 0; for (xx = -1; xx <= 1; ++xx) { if (x + xx < 0 || x + xx >= xs) continue; for (yy = -1; yy <= 1; ++yy) { if (y + yy < 0 || y + yy >= ys) continue; if (field[y+yy][x+xx].live == BOMB) ++sum; } } return sum; } int #ifdef __STDC__ openround(int y, int x) #else openround(y, x) int y, x; #endif { int xx, yy; for (xx = -1; xx <= 1; ++xx) { if (x + xx < 0 || x + xx >= xs) continue; for (yy = -1; yy <= 1; ++yy) { if (y + yy < 0 || y + yy >= ys) continue; if (field[y + yy][x + xx].live == HIDDEN && field[y + yy][x + xx].st == -1) { field[y + yy][x + xx].x = BANG; return 1; } lookaround(y + yy, x + xx); } } return 0; } void #ifdef __STDC__ HandlePanel(XEvent* ev) #else HandlePanel(ev) XEvent* ev; #endif { int x = pressx; int y = pressy; if (done) return; D(printf("(%d,%d) pressed\n", x, y)); if (x < 0 || x >= xs || y < 0 || y >= ys) { printf("!!!! (%d,%d)\n", x,y); return; } if (ev->xbutton.button == Button1) { if (field[y][x].live == HIDDEN) { if (field[y][x].st == -1) { field[y][x].x = BANG; Bomb(); return; } lookaround(y, x); } } else if (ev->xbutton.button == Button2) { if (field[y][x].live == OPEN && field[y][x].st == checkround(y, x)) { if (openround(y, x)) { Bomb(); return; } } } else if (ev->xbutton.button == Button3) { switch (field[y][x].live) { case HIDDEN: field[y][x].live = BOMB; break; case BOMB: field[y][x].live = QUESTION; break; case QUESTION: field[y][x].live = HIDDEN; break; default: goto none; } RedrawPanel(x, y); UpdateDigit(); /*Redraw(ev);*/ } none: if (checkit()) Congraturation(); ; } /* Callback functions */ void #ifdef __STDC__ none(XEvent* dmy) #else none() #endif { } void #ifdef __STDC__ panelPressed(XEvent* ev) #else panelPressed(ev) XEvent* ev; #endif { pressx /= BMS; pressy /= BMS; if (pressx < 0 || pressx >= xs || pressy < 0 || pressy >= ys) return; if (field[pressy][pressx].live == HIDDEN && ev->xbutton.button != Button2) { XCopyPlane(d, pushedtile, panelw, panelgc, 0, 0, BMS, BMS, pressx * BMS, pressy * BMS, 1); XCopyPlane(d, nikoniko, niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); lastin = True; } else funcs = &noneFuncs; } void #ifdef __STDC__ panelLeftPressed(XEvent* ev) #else panelLeftPressed(ev) XEvent* ev; #endif { panelPressed(ev); } void #ifdef __STDC__ panelLeftMotion(XEvent* ev) #else panelLeftMotion(ev) XEvent* ev; #endif { int x = ev->xbutton.x; int y = ev->xbutton.y; x /= BMS; y /= BMS; if (x != pressx || y != pressy) { if (lastin) { XCopyPlane(d, tile, panelw, panelgc, 0, 0, BMS, BMS, pressx*BMS, pressy*BMS, 1); XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); lastin = False; } } else { if (!lastin) { XCopyPlane(d, pushedtile, panelw, panelgc, 0, 0, BMS, BMS, pressx*BMS, pressy*BMS, 1); XCopyPlane(d, nikoniko, niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); lastin = True; } } } void #ifdef __STDC__ panelLeftReleased(XEvent* ev) #else panelLeftReleased(ev) XEvent* ev; #endif { if (lastin) HandlePanel(ev); } #ifndef SLOW_XTERMINAL /* Animate Pannels as pushed down, when middle button is used */ void #ifdef __STDC__ middleAnimatePanels(int px, int py) #else middleAnimatePanels(px, py) int px, py; #endif { int x, y; if (px != pressx || py != pressy) { /* 最初に押したボタンの外である */ if (lastin) { /* たった今ボタンの外に出たところ */ XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); for (x = pressx - 1; x <= pressx + 1; ++x) { for (y = pressy - 1; y <= pressy + 1; ++y) { if (x >= 0 && x < xs && y >= 0 && y < ys && field[y][x].live == HIDDEN) { XCopyPlane(d, tile, panelw, panelgc, 0, 0, BMS, BMS, x*BMS, y*BMS, 1); } } } lastin = False; } } else { if (!lastin) { XCopyPlane(d, nikoniko, niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); for (x = pressx - 1; x <= pressx + 1; ++x) { for (y = pressy - 1; y <= pressy + 1; ++y) { if (x >= 0 && x < xs && y >= 0 && y < ys && field[y][x].live == HIDDEN) { XCopyPlane(d, pushedtile, panelw, panelgc, 0, 0, BMS, BMS, x*BMS, y*BMS, 1); } } } lastin = True; } } } #endif void #ifdef __STDC__ panelMiddlePressed(XEvent* ev) #else panelMiddlePressed(ev) XEvent* ev; #endif { #ifdef SLOW_XTERMINAL panelLeftPressed(ev); #else int x, y; pressx /= BMS; pressy /= BMS; /* fail safe */ if (pressx < 0 || pressx >= xs || pressy < 0 || pressy >= ys) return; if (field[pressy][pressx].live != OPEN || field[pressy][pressx].st != checkround(pressy, pressx)) { funcs = &noneFuncs; return; } lastin = False; /* 最初は、ボタンの外であるとごまかす */ middleAnimatePanels(pressx, pressy); /*funcs = &noneFuncs;*/ #endif } void #ifdef __STDC__ panelMiddleMotion(XEvent* ev) #else panelMiddleMotion(ev) XEvent* ev; #endif { #ifdef SLOW_XTERMINAL int x = ev->xbutton.x / BMS; int y = ev->xbutton.y / BMS; if (x != pressx || y != pressy) { funcs = &noneFuncs; } #else int x = ev->xbutton.x; int y = ev->xbutton.y; x /= BMS; y /= BMS; middleAnimatePanels(x, y); #endif } void #ifdef __STDC__ panelMiddleReleased(XEvent* ev) #else panelMiddleReleased(ev) XEvent* ev; #endif { int x = ev->xbutton.x / BMS; int y = ev->xbutton.y / BMS; /* fool proof */ if (x == pressx && y == pressy) { HandlePanel(ev); } } /* right button */ void #ifdef __STDC__ panelRightPressed(XEvent* ev) #else panelRightPressed(ev) XEvent* ev; #endif { pressx /= BMS; pressy /= BMS; switch (field[pressy][pressx].live) { case HIDDEN: case BOMB: case QUESTION: /* change states immediately */ HandlePanel(ev); funcs = &noneFuncs; break; default: pressy = -1; funcs = &noneFuncs; break; } } void #ifdef __STDC__ panelRightMotion(XEvent* ev) #else panelRightMotion(ev) XEvent* ev; #endif { panelLeftMotion(ev); } void #ifdef __STDC__ panelRightReleased(XEvent* ev) #else panelRightReleased(ev) XEvent* ev; #endif { panelLeftReleased(ev); } /* niko button */ void #ifdef __STDC__ nikoPressed(XEvent* ev) #else nikoPressed(ev) XEvent* ev; #endif { XCopyPlane(d, nikoniko, niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); lastin = True; } void #ifdef __STDC__ nikoMotion(XEvent* ev) #else nikoMotion(ev) XEvent* ev; #endif { int x = ev->xbutton.x; int y = ev->xbutton.y; if (x < 0 || x >= BMS || y < 0 || y >= BMS) { if (lastin) XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); lastin = False; } else { if (!lastin) { XCopyPlane(d, nikoniko, niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); } lastin = True; } } void #ifdef __STDC__ nikoReleased(XEvent* ev) #else nikoReleased(ev) XEvent* ev; #endif { int x = ev->xbutton.x; int y = ev->xbutton.y; if (x < 0 || x >= BMS || y < 0 || y >= BMS) { XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); } else { NewGame(); } } void #ifdef __STDC__ menuPressed(XEvent* ev) #else menuPressed(ev) XEvent* ev; #endif { XMapWindow(d, filepulldown); pressx = pressy = -1; } int #ifdef __STDC__ getMenuItem(int x, int y) #else getMenuItem(x, y) int x, y; #endif { if (x < 0 || x >= 120 || y < 0 || y > pulldownmenuheight + menuheight - 4) { return -1; } y -= menuheight - 4; y /= menuheight; if (y >= 0 && y < sizeOf(menucontents) - 1) return y; return -1; } #define DrawHeight (menuheight) void #ifdef __STDC__ menuMotion(XEvent* ev) #else menuMotion(ev) XEvent* ev; #endif { int x = ev->xbutton.x; int y = ev->xbutton.y; y = getMenuItem(x, y); if (y >= 0) { if (pressy != y && menucontents[y].title[0]) { XDrawRectangle(d, filepulldown, filepulldownbgc, 2, pressy * menuheight, 116, DrawHeight); XDrawRectangle(d, filepulldown, filepulldowngc, 2, y * menuheight, 116, DrawHeight); pressy = y; } } } void #ifdef __STDC__ menuReleased(XEvent* ev) #else menuReleased(ev) XEvent* ev; #endif { int x = ev->xbutton.x; int y = ev->xbutton.y; if ((y = getMenuItem(x, y)) >= 0 && menucontents[y].func) { int i; for (i = 0 ; i < 3; ++i) { XFillRectangle(d, filepulldown, filepulldowngc, 2, y * menuheight, 116, DrawHeight); XDrawString(d, filepulldown, filepulldownbgc, 4, ankascent + menuheight * y, menucontents[y].title, strlen(menucontents[y].title)); XSync(d, False); XFillRectangle(d, filepulldown, filepulldownbgc, 2, y * menuheight, 116, DrawHeight); XDrawString(d, filepulldown, filepulldowngc, 4, ankascent + menuheight * y, menucontents[y].title, strlen(menucontents[y].title)); XSync(d, False); } XUnmapWindow(d, filepulldown); menucontents[y].func(); } else { XUnmapWindow(d, filepulldown); } } ButtonFunc noneFuncs = { none, none, none }; ButtonFunc nikoFuncs = { nikoPressed, nikoMotion, nikoReleased }; ButtonFunc panelLeftFuncs = { panelLeftPressed, panelLeftMotion, panelLeftReleased }; ButtonFunc panelMiddleFuncs = { panelMiddlePressed, panelMiddleMotion, panelMiddleReleased }; ButtonFunc panelRightFuncs = { panelRightPressed, panelRightMotion, panelRightReleased }; ButtonFunc menuFuncs = { menuPressed, menuMotion, menuReleased }; ButtonFunc* funcs = &noneFuncs; void #ifdef __STDC__ Pressed(XEvent* ev) #else Pressed(ev) XEvent* ev; #endif { if (inmotion) return; funcs = &noneFuncs; pressedWin = ev->xany.window; pressx = ev->xbutton.x; pressy = ev->xbutton.y; if (pressedWin == niko) { funcs = &nikoFuncs; } else if (!done && pressedWin == panelw) { switch (ev->xbutton.button) { case Button1: funcs = &panelLeftFuncs; break; case Button2: funcs = &panelMiddleFuncs; break; case Button3: funcs = &panelRightFuncs; break; } } else if (pressedWin == file) { funcs = &menuFuncs; } else if (pressedWin == congraturation) { XUnmapWindow(d, congraturation); } #if HIGH_SCORE else if (pressedWin == highscore) { XUnmapWindow(d, highscore); XStoreName(d, highscore, "High Score"); } #endif else { funcs = &noneFuncs; } funcs->pressed(ev); if (funcs != &noneFuncs && funcs->motion != NULL) { inmotion = True; } } void #ifdef __STDC__ Motion(XEvent* ev) #else Motion(ev) XEvent* ev; #endif { D(printf("Motion\n")); funcs->motion(ev); } void #ifdef __STDC__ Released(XEvent* ev) #else Released(ev) XEvent* ev; #endif { funcs->released(ev); funcs = &noneFuncs; XCopyPlane(d, bmp_niko[nikop], niko, nikogc, 0, 0, BMS, BMS, 0, 0, 1); pressedWin = 0; inmotion = False; } void #ifdef __STDC__ Enter(XEvent* ev) #else Enter(ev) XEvent* ev; #endif { } void #ifdef __STDC__ Leave(XEvent* ev) #else Leave(ev) XEvent* ev; #endif { } void MainLoop(VOID) { XEvent ev; struct timeval timeout; fd_set mask; fd_set readfds; int nfds; int nfound; int got_one; /* setup timeouts*/ timeout.tv_sec = 10000; timeout.tv_usec = 0; FD_ZERO(&mask); FD_SET(ConnectionNumber(d), &mask); nfds = ConnectionNumber(d) + 1; #if HIGH_SCORE init_highscore(); read_highscore(); write_highscore(); #endif #if HAS_RANDOM srandom(time(NULL)); #else srand(time(NULL)); #endif for (;_;) { got_one = False; while (!got_one) { if (XEventsQueued(d, QueuedAfterReading) > 0) { XNextEvent(d, &ev); got_one = True; continue; } else XFlush(d); readfds = mask; timeout.tv_sec = (start && !done ) ? 0 : 10000; timeout.tv_usec = 500000; nfound = select(nfds, &readfds, NULL, NULL, &timeout); if (nfound <= 0 || !FD_ISSET(nfds - 1, &readfds)) { UpdateCounter(False); } } switch (ev.type) { case Expose: RedrawEachParts(&ev); break; case ButtonPress: Pressed(&ev); D(printf("ButtonPress\n")); break; case ButtonRelease: Released(&ev); break; case MotionNotify: Motion(&ev); break; case EnterNotify: Enter(&ev); break; case LeaveNotify: Leave(&ev); break; } } }