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

solitaire.c

/*
 * Solitaire game (name unknown)
 *
 * Copyright (C) Evan Harris, 1991, 1994
 *
 * Permission is granted to freely redistribute and modify this code,
 * providing the author(s) get credit for having written it.
 */

#include "solitaire.h"
#include <stdlib.h>


#define U_MOVE                1
#define U_MOVE_EXPOSE         3

struct undo {
    unsigned char type;
    unsigned char card;
    short         from;
    struct undo   *next;
};


unsigned char     column[COLUMNS];        /* First card of column */
short       cards[NUMCARDS];        /* Positions of cards */
unsigned char     next[NUMCARDS];               /* Card underneath */
unsigned char     hidden[NUMCARDS];       /* Cards which are face down */
struct undo *undoinfo = NULL;


void main(int argc, char **argv)
{
    short cmd, dest;

    InitDisplay(argc, argv);

    InitRandom(NEW);
    Deal();

    for (;;) {
      cmd = GetCmd();
      if (cmd == QUIT) {
          EndDisplay();
          exit(0);
      }
      if (cmd == NEWGAME) {
          InitRandom(NEW);
          Deal();
      }
      else if (cmd == RESTART) {
          InitRandom(LAST);
          Deal();
      }
      else if (cmd == UNDO) {
          Undo();
      }
      else if (ISCARD(cmd)) {
          dest = FindDest((unsigned char)cmd);
          if (dest != NOPOSN)
            MakeMove((unsigned char)cmd, dest);
      }
    }

    /* Never reached */
}


void Deal()
{
    unsigned char i, j;
    short r;

    /* Initialise the deck */
    for (i = 0; i < NUMCARDS; i++) {
      cards[i] = NOPOSN;
      next[i] = NOCARD;
    }
            
    /* Deal the deck */
    for (i = 0; i < NUMCARDS; i++) {
      r = Random(NUMCARDS - i);
      for (j = 0; j < NUMCARDS && r >= 0; j++) {
          if (cards[j] == NOPOSN)
            r--;
      }
      r = j - 1;

      cards[r] = POSN(i % 7, i / 7);
      if (i / 7 == 0)
          column[i % 7] = r;
      else {
          for (j = 0; cards[j] != POSN(i % 7, i / 7 - 1); j++)
            ;
          next[j] = r;
      }
      if ((i / 7 <= 2) && (i % 7 >= 4))
          hidden[r] = 1;
      else
          hidden[r] = 0;
    }

    for (i = 0; i < 7; i++)
      DisplayColumn((short)i);

    return;
}


short FindDest(unsigned char card)
{
    unsigned char i, c;

    if (TYPE(card) == KING) {
      if (ROW(cards[card]) == 0)
          return NOPOSN;
      for (i = 0; i < COLUMNS; i++)
          if (column[i] == NOCARD)
            return (short)POSN(i, 0);
    }
    else {
      for (i = 0; i < COLUMNS; i++)
          if (i != COL(cards[card])) {
            c = column[i];
            while (next[c] != NOCARD)
                c = next[c];
            if (c == CARD(SUIT(card), TYPE(card) + 1))
                return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
          }
    }

    return NOPOSN;
}


void MakeMove(unsigned char card, short dest)
{
    short col, row, oldcol;
    unsigned char c, i;
    unsigned char h = 0;

    col = COL(dest);
    row = ROW(dest);
    oldcol = -1;

    for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
      if (column[i] == card) {
          column[i] = NOCARD;
          oldcol = i;
      }
    }
    for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
      if (next[i] == card) {
          if (hidden[i]) {
            hidden[i] = 0;
            h = 1;
          }
          next[i] = NOCARD;
          oldcol = COL(cards[i]);
      }
    }
    if (h)
      AddUndo(U_MOVE_EXPOSE, card, cards[card]);
    else
      AddUndo(U_MOVE, card, cards[card]);

    if (row > 0) {
      c = column[col];
      while (next[c] != NOCARD)
          c = next[c];
      next[c] = card;
    }
    else
      column[col] = card;
    while (card != NOCARD) {
      cards[card] = POSN(col, row++);
      card = next[card];
    }

    DisplayColumn(oldcol);
    DisplayColumn(col);

    return;
}


void AddUndo(unsigned char type, unsigned char card, short from)
{
    struct undo *undo;

    undo = (struct undo *)malloc(sizeof(struct undo));
    undo->type = type;
    undo->card = card;
    undo->from = from;
    undo->next = undoinfo;
    undoinfo = undo;

    return;
}


void Undo()
{
    struct undo *undo = undoinfo;

    if (undo == NULL)
      return;

    switch (undo->type) {
      case U_MOVE:
      UndoMove(undo->card, (short)COL(undo->from), 0);
      break;
      case U_MOVE_EXPOSE:
      UndoMove(undo->card, (short)COL(undo->from), 1);
      break;
    }

    undoinfo = undoinfo->next;
    free(undo);

    return;
}


void UndoMove(unsigned char card, short col, unsigned char expose)
{
    unsigned char c, row;
    short oldcol;

    oldcol = COL(cards[card]);
    c = column[oldcol];
    if (c == card) {
      column[oldcol] = NOCARD;
    } else {
      while (next[c] != card)
          c = next[c];
      next[c] = NOCARD;
    }

    c = column[col];
    row = 0;
    if (c == NOCARD) {
      column[col] = card;
      cards[card] = POSN(col, row);
      c = next[card];
    } else {
      while (next[c] != NOCARD) {
          c = next[c];
          row++;
      }
      if (expose)
          hidden[c] = 1;
      next[c] = card;
      cards[card] = POSN(col, ++row);
      c = next[card];
    }
    while (c != NOCARD) {
      cards[c] = POSN(col, ++row);
      c = next[c];
    }
    DisplayColumn(oldcol);
    DisplayColumn(col);

    return;
}

Generated by  Doxygen 1.6.0   Back to index