Logo Search packages:      
Sourcecode: vgagamespack version File versions

milinux.c

/*
 * Mines
 *
 * Copyright (C) Evan Harris, 1994-1998.
 *
 * Permission is granted to freely redistribute and modify this code,
 * providing the author(s) get credit for having written it.
 */

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <vga.h>
#ifndef NOMOUSE
#include <vgamouse.h>
#endif

#include "mines.h"
#include "misquare.h"
#include "vga16.h"
#include "mouse.h"
#include "key.h"


#if !defined(CLOCKS_PER_SECOND) && defined(CLOCKS_PER_SEC)
#define CLOCKS_PER_SECOND CLOCKS_PER_SEC
#endif


#define SCREENMODE G640x480x16
#define SCREENWIDTH 640
#define SCREENHEIGHT 480

#define BOARDWIDTH 512
#define BOARDHEIGHT SCREENHEIGHT

#define VERSION "MINES v1.4"
#define VERSIONLEFT (SCREENWIDTH - 8 * strlen(VERSION))
#define VERSIONBOTTOM 168

#define QUITLEFT (SCREENWIDTH - 80)
#define QUITBOTTOM 76
#define QUITTOP (QUITBOTTOM - 15)
#define QUITRIGHT (QUITLEFT + 79)

#define NEWGAMELEFT QUITLEFT
#define NEWGAMEBOTTOM 48
#define NEWGAMETOP (NEWGAMEBOTTOM - 15)
#define NEWGAMERIGHT (NEWGAMELEFT + 79)

#define WINLEFT (SCREENWIDTH - 72)
#define WINBOTTOM 312

#define MINESLEFT (SCREENWIDTH - 80)
#define MINESBOTTOM 248

#define TIMELEFT (SCREENWIDTH - 40)
#define TIMEBOTTOM 280

#define SQUARESIZE 16

#define MOUSEKEYMOVE 8

#define PALETTESIZE 12

int palette[PALETTESIZE * 3] = {
    0x00, 0x00, 0x00,         /* black */
    0x20, 0x20, 0x20,         /* grey */
    0x18, 0x18, 0x18,         /* dark grey */
    0x00, 0x00, 0x3f,         /* blue */
    0x3f, 0x00, 0x00,         /* red */
    0x3f, 0x3f, 0x00,         /* yellow */
    0x3f, 0x3f, 0x3f,         /* white */
    0x00, 0x3f, 0x00,         /* green */
    0x00, 0x3f, 0x3f,         /* cyan */
    0x3f, 0x00, 0x3f,         /* magenta */
    0x3f, 0x29, 0x00,         /* orange */
    0x3b, 0x20, 0x3b,         /* violet */
};

#define TEXTFG 6
#define TEXTBG 0
#define BUTTONFG 0
#define BUTTONBG 1
#define MINESFG 1
#define TIMEFG 5
#define MOUSEFG 4
#define MOUSEDARKFG 5

#define BTNNONE 0
#define BTNLEFT 1
#define BTNRIGHT 2
#define BTNMIDDLE 3
#define BTNBOTH 4

#define UNKNOWN -1

#ifndef MOUSESAMPLERATE
#define MOUSESAMPLERATE MOUSE_DEFAULTSAMPLERATE
#endif

#define USLEEP_TIME 30000


void ShowTime(long t);


static int boardleft, boardtop, boardxsize, boardysize;


void
InitDisplay(int width, int height)
{
    vga_disabledriverreport();
    vga_init();
#if !defined(USEMOUSEFUNCS) && !defined(NOMOUSE)
    vga_setmousesupport(1);
#endif

    if (vga_setmode(SCREENMODE) != 0) {
      fprintf(stderr, "Mode %s not available!\n",
            vga_getmodename(SCREENMODE));
      exit(1);
    }

#if defined(USEMOUSEFUNCS) && !defined(NOMOUSE)
    mouse_init("/dev/mouse", vga_getmousetype(), MOUSESAMPLERATE);
    mouse_setxrange(0, SCREENWIDTH - 1);
    mouse_setyrange(0, SCREENHEIGHT - 1);
    mouse_setwrap(MOUSE_NOWRAP);
#endif

    vga16_init();

    vga_setpalvec(0, PALETTESIZE, &palette[0]);

    vga16_text(NEWGAMELEFT, NEWGAMEBOTTOM, " NEW GAME ", BUTTONFG, BUTTONBG);
    vga16_text(QUITLEFT, QUITBOTTOM, "   QUIT   ", BUTTONFG, BUTTONBG);
    vga16_text(VERSIONLEFT, VERSIONBOTTOM, VERSION, TEXTFG, TEXTBG);

    boardleft = ((BOARDWIDTH - width * SQUARESIZE) / 16) * 8;
    boardtop = (BOARDHEIGHT - height * SQUARESIZE) / 2;
    boardxsize = width;
    boardysize = height;
}


void
EndDisplay()
{
    vga_setmode(TEXT);
#if defined(USEMOUSEFUNCS) && !defined(NOMOUSE)
    mouse_close();
#endif    
}


static time_t starttime;
static int stoptime;


void
NewGame(int w, int h)
{
    int x, y;
    
    vga16_text(WINLEFT, WINBOTTOM, "        ", MINESFG, TEXTBG);
    for (x = 0; x < w; x++) {
      for (y = 0; y < h; y++) {
          ShowSquare(x, y, SQ_COVERED);
      }
    }
    starttime = time(NULL);
    stoptime = 0;
    ShowTime(0);
}


void
GameOver(int status)
{
    stoptime = 1;

    if (status == WIN) {
      vga16_text(WINLEFT, WINBOTTOM, "YOU WIN!", MINESFG, TEXTBG);
    } else if (status == LOSE) {
      vga16_text(WINLEFT, WINBOTTOM, "YOU LOSE", MINESFG, TEXTBG);
    }
}


void
MinesLeft(int m)
{
    char s[16];
    
    sprintf(s, "Mines: %3d", m);
    vga16_text(MINESLEFT, MINESBOTTOM, s, MINESFG, TEXTBG);
}


void
ShowTime(long t)
{
    static long lastt = -1;
    char buf[16];

    if (!stoptime && t != lastt) {
      if (t >= 3600) {
          sprintf(buf, "%ld:%02ld:%02ld", t / 3600, (t % 3600) / 60, t % 60);
      } else if (t >= 60) {
          sprintf(buf, "%ld:%02ld", t / 60, t % 60);
      } else {
          sprintf(buf, "%ld", t);
      }
      if (t == 0) {
          vga16_text(TIMELEFT - 40, TIMEBOTTOM, "          ",
                   TIMEFG, TEXTBG);
      }
      vga16_text(TIMELEFT - 4 * strlen(buf), TIMEBOTTOM, buf,
               TIMEFG, TEXTBG);
      lastt = t;
    }
}


static int oldx = -1, oldy, oldcolour[40];


void
MoveMousePointer(int x, int y)
{
    if (x != oldx || y != oldy) {
      if (oldx != -1) {
          RestoreUnderMousePointer(oldx, oldy, SCREENWIDTH, SCREENHEIGHT,
                             oldcolour);
      }
      SaveUnderMousePointer(x, y, SCREENWIDTH, SCREENHEIGHT, oldcolour);
      RenderMousePointer(x, y, MOUSEFG, MOUSEDARKFG,
                     SCREENWIDTH, SCREENHEIGHT);
      oldx = x;
      oldy = y;
    }
}


int
ParseMousePosition(int x, int y, int btn)
{
    if (btn == BTNLEFT
      && x >= NEWGAMELEFT && x <= NEWGAMERIGHT
      && y >= NEWGAMETOP && y <= NEWGAMEBOTTOM) {
      return packcmd(NEWGAME, 0, 0);
    } else if (btn == BTNLEFT
             && x >= QUITLEFT && x <= QUITRIGHT
             && y >= QUITTOP && y <= QUITBOTTOM) {
      return packcmd(QUIT, 0, 0);
    } else if ((x - boardleft) / SQUARESIZE >= 0
             && (x - boardleft) / SQUARESIZE < boardxsize
             && (y - boardtop) / SQUARESIZE >= 0
             && (y - boardtop) / SQUARESIZE < boardysize) {
      if (btn == BTNRIGHT) {
          return packcmd(PROTECT, (x - boardleft) / SQUARESIZE,
                     (y - boardtop) / SQUARESIZE);
      } else if (btn == BTNMIDDLE || btn == BTNBOTH) {
          return packcmd(CHECK_AROUND, (x - boardleft) / SQUARESIZE,
                     (y - boardtop) / SQUARESIZE);
      } else if (btn == BTNNONE) {
          return packcmd(UNCHECK_AROUND, (x - boardleft) / SQUARESIZE,
                     (y - boardtop) / SQUARESIZE);
      } else {
          return packcmd(DETONATE, (x - boardleft) / SQUARESIZE,
                     (y - boardtop) / SQUARESIZE);
      }
    }
    return UNKNOWN;
}


int
GetMove()
{
    int move = UNKNOWN, key;

#if !defined(NOMOUSE)
    static int lastbutton = 0, b_x = 0, b_y = 0;
    int x, y, button;
    
    if (oldx == -1) {
      x = mouse_getx();
      y = mouse_gety();
      MoveMousePointer(x, y);
    }
#else
    MoveMousePointer(0, 0);
#endif
    
    while (move == UNKNOWN) {
      usleep(USLEEP_TIME);    /* don't chew up as much CPU */
      
#if !defined(NOMOUSE)
      if (mouse_update()) {
          x = mouse_getx();
          y = mouse_gety();
          button = mouse_getbutton();

          MoveMousePointer(x, y);

          if (lastbutton == 0 ||
            ((lastbutton & (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
             &&
             ((button & (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
              == (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON)))) {
            
            if ((button & (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
                == (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON)) {
                move = ParseMousePosition(x, y, BTNBOTH);
                b_x = x;
                b_y = y;
            } else if (button & MOUSE_LEFTBUTTON) {
                move = ParseMousePosition(x, y, BTNLEFT);
            } else if (button & MOUSE_RIGHTBUTTON) {
                move = ParseMousePosition(x, y, BTNRIGHT);
            } else if (button & MOUSE_MIDDLEBUTTON) {
                move = ParseMousePosition(x, y, BTNMIDDLE);
                b_x = x;
                b_y = y;
            }
          } else if (((lastbutton & MOUSE_MIDDLEBUTTON)
                  && (button & MOUSE_MIDDLEBUTTON) == 0)
                   ||
                   (((lastbutton & (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
                   == (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
                  && ((button & (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON))
                      != (MOUSE_LEFTBUTTON | MOUSE_RIGHTBUTTON)))) {
            move = ParseMousePosition(b_x, b_y, BTNNONE);
          }
          lastbutton = button;
      }
#endif

      if ((key = key_getkey()) != -1 ) {
          switch (key) {
            case 'n':
            case 'N':
            move = packcmd(NEWGAME, 0, 0);
            break;
            case 'q':
            case 'Q':
            move = packcmd(QUIT, 0, 0);
            break;
            case KEY_CURSORUP:
            if (oldy >= MOUSEKEYMOVE) {
                MoveMousePointer(oldx, oldy - MOUSEKEYMOVE);
            }
            break;
            case KEY_CURSORDOWN:
            if (oldy < SCREENHEIGHT - MOUSEKEYMOVE) {
                MoveMousePointer(oldx, oldy + MOUSEKEYMOVE);
            }
            break;
            case KEY_CURSORLEFT:
            if (oldx >= MOUSEKEYMOVE) {
                MoveMousePointer(oldx - MOUSEKEYMOVE, oldy);
            }
            break;
            case KEY_CURSORRIGHT:
            if (oldx < SCREENWIDTH - MOUSEKEYMOVE) {
                MoveMousePointer(oldx + MOUSEKEYMOVE, oldy);
            }
            break;
            case '\n':
            case ',':
            move = ParseMousePosition(oldx, oldy, BTNLEFT);
            break;
            case ' ':
            case '/':
            move = ParseMousePosition(oldx, oldy, BTNRIGHT);
            break;
            case '\014':
            case 'r':
            case 'R':
            vga16_redrawscreen();
            break;
            default:
            break;
          }
      }

      ShowTime(time(NULL) - starttime);
    }

    return move;
}


void
ShowSquare(int x, int y, int sq)
{
    int l;
    int renderpointer = 0;
    
    if (oldx != -1
      && oldx >= boardleft + x * SQUARESIZE - 8
      && oldx <= boardleft + (x + 1) * SQUARESIZE
      && oldy >= boardtop + y * SQUARESIZE - 8
      && oldy <= boardtop + (y + 1) * SQUARESIZE) {
      RestoreUnderMousePointer(oldx, oldy, SCREENWIDTH, SCREENHEIGHT,
                         oldcolour);
      renderpointer = 1;
    }

    for (l = 0; l < SQUARESIZE; l++) {
      vga16_drawscansegment(squarelines[square[sq][l]],
                        boardleft + x * SQUARESIZE,
                        boardtop + y * SQUARESIZE + l, SQUARESIZE);

    }

    if (renderpointer) {
      SaveUnderMousePointer(oldx, oldy, SCREENWIDTH, SCREENHEIGHT,
                        oldcolour);
      RenderMousePointer(oldx, oldy, MOUSEFG, MOUSEDARKFG,
                     SCREENWIDTH, SCREENHEIGHT);
    }
}

Generated by  Doxygen 1.6.0   Back to index