Logo Search packages:      
Sourcecode: vgacardgames version File versions  Download package

kllinux.c

/*
 * Klondike
 *
 * Copyright (C) Evan Harris, 1991, 1994, 1995.
 *
 * 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 <vga.h>
#include <vgamouse.h>

#include "vga16.h"
#include "mouse.h"
#include "key.h"
#include "klondike.h"
#include "common.h"


#define KL_SCREENMODE G640x480x16
#define KL_SCREENWIDTH 640
#define KL_SCREENHEIGHT 480

#define KL_TEXTFG 1
#define KL_TEXTBG 0
#define KL_BUTTONFG 2
#define KL_BUTTONBG 6
#define KL_MOUSEFG 5
#define KL_MOUSEDARKFG 2
#define KL_OUTLINE 6

#define NUMCARDIMAGES 52
#define CARDACTUALWIDTH 53
#define CARDIMAGEWIDTH 56
#define CARDIMAGEHEIGHT 80

#define VERSION "KLONDIKE\n  v1.3"
#define VERSIONLEFT (KL_SCREENWIDTH - 72)

#ifndef CARDSFILE
#define CARDSFILE "Cards56x80"
#endif
#ifndef CARDSMOUSESAMPLERATE
#define CARDSMOUSESAMPLERATE MOUSE_DEFAULTSAMPLERATE
#endif

#define USLEEP_TIME 30000


#define CARDTOIMAGE(card)     (card % NUMCARDIMAGES)

#define BITWIDTH CARDIMAGEWIDTH /* multiple of 8 */
#define BITHEIGHT CARDIMAGEHEIGHT
#define BITSHOWLEFT 24        /* multiple of 8 */
#define BITTOP 24
#define COLWIDTH (BITWIDTH + 8)
#define TOPROWHEIGHT    (BITHEIGHT + 4)


#define KL_QUITLEFT (KL_SCREENWIDTH - 80)
#define KL_QUITRIGHT (KL_QUITLEFT + 80)
#define KL_QUITBOTTOM 104
#define KL_QUITTOP (KL_QUITBOTTOM - 16)

#define KL_NEWGAMELEFT KL_QUITLEFT
#define KL_NEWGAMERIGHT KL_QUITRIGHT
#define KL_NEWGAMEBOTTOM 48
#define KL_NEWGAMETOP (KL_NEWGAMEBOTTOM - 16)

#define KL_RESTARTLEFT KL_QUITLEFT
#define KL_RESTARTRIGHT KL_QUITRIGHT
#define KL_RESTARTBOTTOM 76
#define KL_RESTARTTOP (KL_RESTARTBOTTOM - 16)


#define STOCKLEFT 0
#define STOCKTOP 0
#define PILELEFT COLWIDTH
#define PILETOP 0
#define FOUNDLEFT (3 * COLWIDTH)
#define FOUNDTOP 0


#define KL_PALETTESIZE 7

int palette[KL_PALETTESIZE * 3] = {
    0x00, 0x20, 0x00,         /* green */
    0x3f, 0x3f, 0x3f,         /* white */
    0x00, 0x00, 0x00,         /* black */
    0x37, 0x00, 0x00,         /* red */
    0x00, 0x00, 0x20,         /* blue */
    0x2f, 0x3f, 0x00,         /* yellow */
    0x1a, 0x1a, 0x1a,         /* grey */
};

#define MIN(a, b) ((a) < (b) ? (a) : (b))
static void LoadCards(char *file);
static long GetMouseButton(void);
static long WhileMouseButton(void);
static int ParsePos(long pos, int downcard, int buttonup);

static unsigned char ***imageCard;
static unsigned char **backCard;
static unsigned char **outlineCard;
static unsigned char *blankLine;


void
InitDisplay(int argc, char **argv)
{
    vga_disabledriverreport();
    vga_init();
#if !defined(CARDSMOUSE)
    vga_setmousesupport(1);
#endif
    
    if (vga_setmode(KL_SCREENMODE) != 0) {
      fprintf(stderr, "Mode %s not available!\n",
            vga_getmodename(KL_SCREENMODE));
      exit(1);
    }

#if defined(CARDSMOUSE)
    mouse_init("/dev/mouse", vga_getmousetype(), CARDSMOUSESAMPLERATE);
    mouse_setxrange(0, KL_SCREENWIDTH - 1);
    mouse_setyrange(0, KL_SCREENHEIGHT - 1);
    mouse_setwrap(MOUSE_NOWRAP);
#endif

    vga16_init();

    LoadCards(CARDSFILE);

    blankLine = (unsigned char *)calloc(KL_SCREENWIDTH, sizeof(unsigned char));
    if (blankLine == NULL) {
      fprintf(stderr, "Error: cannot get memory for blankLine\n");
      exit(1);
    }

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

    vga16_text(KL_NEWGAMELEFT, KL_NEWGAMEBOTTOM, " NEW GAME ",
             KL_BUTTONFG, KL_BUTTONBG);
    vga16_text(KL_RESTARTLEFT, KL_RESTARTBOTTOM, " RESTART  ",
             KL_BUTTONFG, KL_BUTTONBG);
    vga16_text(KL_QUITLEFT, KL_QUITBOTTOM, "   QUIT   ",
             KL_BUTTONFG, KL_BUTTONBG);

    vga16_text(VERSIONLEFT, 200, VERSION, KL_TEXTFG, KL_TEXTBG);
}


static void
LoadCards(char *file)
{
    int i, j, k, l, c, colour;
    FILE *f;

    f = fopen(file, "r");
    if (f == NULL) {
      fprintf(stderr, "Cannot find '%s'\n", file);
      exit(1);
    }

    imageCard = (unsigned char ***)malloc(NUMCARDIMAGES
                                * sizeof(unsigned char **));
    if (imageCard == NULL) {
      fprintf(stderr, "Error: cannot get memory for imageCard\n");
      exit(1);
    }
    for (i = 0; i < NUMCARDIMAGES; i++) {
      imageCard[i] = (unsigned char **)malloc(CARDIMAGEHEIGHT
                                    * sizeof(unsigned char *));
      if (imageCard == NULL) {
          fprintf(stderr, "Error: cannot get memory for imageCard[%d]\n",
                i);
          exit(1);
      }
      for (j = 0; j < CARDIMAGEHEIGHT; j++) {
          imageCard[i][j] = (unsigned char *)malloc(CARDIMAGEWIDTH
                                          * sizeof(unsigned char));
          if (imageCard[i][j] == NULL) { 
            fprintf(stderr,
                  "Error: cannot get memory for imageCard[%d][%d]\n",
                  i, j);
            exit(1);
          }
          
          if (SUIT(i) == SPADES || SUIT(i) == CLUBS) {
            colour = 2;
          } else {
            colour = 3;
          }
          if (TYPE(i) < JACK) {
            for (k = 0; k < CARDIMAGEWIDTH / 8; k++) {
                if ((c = getc(f)) == EOF) {
                  fprintf(stderr, "Unexpected EOF in '%s'\n", file);
                  exit(1);
                }
                for (l = 0; l < 8; l++) {
                  imageCard[i][j][8 * k + l] =
                      (c & 1 << (7 - l)) ? colour : 1;
                }
            }
            for (k = CARDACTUALWIDTH; k < CARDIMAGEWIDTH; k++) {
                imageCard[i][j][k] = 0;
            }
          } else {
            for (k = 0; k < CARDIMAGEWIDTH / 2; k++) {
                if ((c = getc(f)) == EOF) {
                  fprintf(stderr, "Unexpected EOF in '%s'\n", file);
                  exit(1);
                }
                imageCard[i][j][2 * k] = (unsigned char)c >> 4;
                imageCard[i][j][2 * k + 1] = (unsigned char)c & 0xf;
            }
          }
      }
    }

    fclose(f);

    backCard = malloc(CARDIMAGEHEIGHT * sizeof(unsigned char *));
    outlineCard = malloc(CARDIMAGEHEIGHT * sizeof(unsigned char *));
    if (backCard == NULL || outlineCard == NULL) {
      fprintf(stderr, "Error: cannot get memory for cards");
      exit(1);
    }
    for (i = 0; i < CARDIMAGEHEIGHT; i++) {
      backCard[i] = malloc(CARDIMAGEWIDTH * sizeof(unsigned char));
      outlineCard[i] = calloc(CARDIMAGEWIDTH, sizeof(unsigned char));
      if (backCard[i] == NULL || outlineCard[i] == NULL) {
          fprintf(stderr, "Error: cannot get memory for cards");
          exit(1);
      }
    }
    for (i = 0; i < CARDACTUALWIDTH; i++) {
      outlineCard[0][i] = KL_OUTLINE;
      outlineCard[CARDIMAGEHEIGHT - 1][i] = KL_OUTLINE;
    }
    for (i = 0; i < CARDIMAGEHEIGHT; i++) {
      outlineCard[i][0] = KL_OUTLINE;
      outlineCard[i][CARDACTUALWIDTH - 1] = KL_OUTLINE;
    }
    for (i = 0; i < CARDIMAGEHEIGHT; i++) {
      for (j = 0; j < CARDACTUALWIDTH; j++) {
          if ((i / 4) % 2 == (j / 4) % 2) {
            backCard[i][j] = 4;
          } else {
            backCard[i][j] = 1;
          }
      }
      for (; j < CARDIMAGEWIDTH; j++) {
          backCard[i][j] = 0;
      }
    }
}


static unsigned char columnTop[COLUMNS];

/* We redisplay a whole column, rather than do anything tricky. */
void
DisplayColumn(short col)
{
    unsigned char **image;
    int card, length, row, height, line;
    int bittop = BITTOP;
      
    if (col == STOCK || col == PILE) {
      DisplayStockPile();
      return;
    }

    for (card = column[col], length = 0; card != NOCARD; card = next[card])
      length++;

    if (length > 0 && (KL_SCREENHEIGHT - TOPROWHEIGHT) / length < bittop)
      bittop = (KL_SCREENHEIGHT - TOPROWHEIGHT) / length;
    columnTop[col] = bittop;

    card = column[col];
    row = TOPROWHEIGHT;
    col = col * COLWIDTH;

    while (card != NOCARD && row < KL_SCREENHEIGHT - 1) {
      if (hidden[card])
          image = backCard;
      else
          image = imageCard[CARDTOIMAGE(card)];
      if (next[card] == NOCARD)
          height = BITHEIGHT;
      else
          height = bittop;
      if (row + height >= KL_SCREENHEIGHT)
          height -= row + height - KL_SCREENHEIGHT + 1;

      for (line = 0; line < height; line++) {
          vga16_drawscansegment(image[line], col, row + line, BITWIDTH);
      }

      row += height;
      card = next[card];
    }
    for (; row < KL_SCREENHEIGHT; row++) {
      vga16_drawscansegment(blankLine, col, row, BITWIDTH);
    }

    return;
}


void
DisplayStockPile()
{
    unsigned char **card;
    int line;
    
    if (stock == NOCARD) {
      card = outlineCard;
    } else {
      card = backCard;
    }
    for (line = 0; line < CARDIMAGEHEIGHT; line++) {
      vga16_drawscansegment(card[line], STOCKLEFT, STOCKTOP + line,
                        BITWIDTH);
    }
    if (pile == NOCARD) {
      card = outlineCard;
    } else {
      card = imageCard[CARDTOIMAGE(pile)];
    }
    for (line = 0; line < CARDIMAGEHEIGHT; line++) {
      vga16_drawscansegment(card[line], PILELEFT, PILETOP + line, BITWIDTH);
    }
}


void
DisplayFoundations()
{
    unsigned char **card;
    int i, line, foundleft;

    foundleft = FOUNDLEFT;
    for (i = 0; i < NUMSUITS; i++) {
      if (foundation[i] == 0) {
          card = outlineCard;
      } else {
          card = imageCard[CARD(i % 4, foundation[i] - 1)];
      }
      for (line = 0; line < CARDIMAGEHEIGHT; line++) {
          vga16_drawscansegment(card[line], foundleft, FOUNDTOP + line,
                          BITWIDTH);
      }
      foundleft += COLWIDTH;
    }
}


short
GetCmd()
{
    int c, c1;
    
    for (c = NOCARD; c == NOCARD;) {
      c = GetMouseButton();
      c1 = WhileMouseButton();
      if (c >= 0) {
          c = ParsePos(c, -1, 0);
          c1 = ParsePos(c1, c, 1);

          if (c == c1 && (c >= 0 || c == FROMSTOCK)) {
            return c;
          }
          if (c >= 0 && c1 == TOFOUNDATION) {
            return TOHINT(FOUNDATION) | c;
          }
          if (c >= 0 && ISCOLSPEC(c1)) {
            return TOHINT(SPECTOCOL(c1)) | c;
          }
          
          c = NOCARD;
      }
    }

    return c;
}


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

static long
GetMouseButton()
{
    int x, y, button, key;

    x = mouse_getx();
    y = mouse_gety();
    if (x != oldx || y != oldy) {
      if (oldx != -1) {
          RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
      }
      SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
      RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
      oldx = x;
      oldy = y;
    }
      
    for (;;) {
      usleep(USLEEP_TIME);    /* don't chew up as much CPU */

      if (mouse_update()) {
          x = mouse_getx();
          y = mouse_gety();
          button = mouse_getbutton();

          if (x != oldx || y != oldy) {
            if (oldx != -1) {
                RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
            }
            SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
            RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
            oldx = x;
            oldy = y;
          }
      
          if (button & MOUSE_LEFTBUTTON) {
            break;
          }
      }
      if ((key = key_getkey()) != -1) {
          switch (key) {
            case 'n':
            case 'N':
            return NEWGAME;
            case 'r':
            case 'R':
            return RESTART;
            case 'q':
            case 'Q':
            return QUIT;
            case '\014':
            vga16_redrawscreen();
            break;
            default:
            break;
          }
      }
    }

    if (x >= KL_NEWGAMELEFT && x < KL_NEWGAMERIGHT
      && y > KL_NEWGAMETOP && y <= KL_NEWGAMEBOTTOM) {
      return NEWGAME;
    }
    if (x >= KL_RESTARTLEFT && x < KL_RESTARTRIGHT
      && y > KL_RESTARTTOP && y <= KL_RESTARTBOTTOM) {
      return RESTART;
    }
    if (x >= KL_QUITLEFT && x < KL_QUITRIGHT
      && y > KL_QUITTOP && y <= KL_QUITBOTTOM) {
      return QUIT;
    }

    return (x << 9) | y;
}


static long
WhileMouseButton()
{
    int x, y, button;

    for (;;) {
      usleep(USLEEP_TIME);    /* don't chew up as much CPU */

      mouse_update();
      x = mouse_getx();
      y = mouse_gety();
      button = mouse_getbutton();

      if (x != oldx || y != oldy) {
          if (oldx != -1) {
            RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
          }
          SaveUnderMousePointer(x, y, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
          RenderMousePointer(x, y, KL_MOUSEFG, KL_MOUSEDARKFG, KL_SCREENWIDTH, KL_SCREENHEIGHT);
          oldx = x;
          oldy = y;
      }
      
      if (!(button & MOUSE_LEFTBUTTON)) {
          break;
      }
    }

    if (oldx != -1) {
      RestoreUnderMousePointer(oldx, oldy, KL_SCREENWIDTH, KL_SCREENHEIGHT, oldcolour);
    }
    oldx = -1;

    return (x << 9) | y;
}


static int
ParsePos(long pos, int downcard, int buttonup)
{
    int x, y, card, row, bittop;
    
    x = pos >> 9;
    y = pos & 0x1ff;
    if (x >= STOCKLEFT && x < STOCKLEFT + BITWIDTH
      && y >= STOCKTOP && y < STOCKTOP + CARDIMAGEHEIGHT) {
      return FROMSTOCK;
    }
    if (x >= STOCKLEFT + COLWIDTH && x < STOCKLEFT + COLWIDTH + BITWIDTH
      && y >= STOCKTOP && y < STOCKTOP + CARDIMAGEHEIGHT) {
      return pile;
    }
    if (buttonup
      && x >= FOUNDLEFT && x < FOUNDLEFT + NUMSUITS * COLWIDTH
      && y >= FOUNDTOP && y < FOUNDTOP + CARDIMAGEHEIGHT) {
      return TOFOUNDATION;
    }

    if (x / COLWIDTH > 6 || y < TOPROWHEIGHT ||
      (x % COLWIDTH) / BITWIDTH > 0) {
      return NOCARD;
    }

    card = column[x / COLWIDTH];
    bittop = columnTop[x / COLWIDTH];
    row = TOPROWHEIGHT;

    while (card != NOCARD) {
      if ((next[card] != NOCARD && y >= row && y < row + bittop)
          || (next[card] == NOCARD && y >= row && y < row + BITHEIGHT)) {
          if (!hidden[card] && (downcard == -1 || downcard == card)) {
            return card;
          }
      }
      card = next[card];
      row += bittop;
    }
    if (buttonup) {
      return COLTOSPEC(x / COLWIDTH);
    }

    return NOCARD;
}

Generated by  Doxygen 1.6.0   Back to index