home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * Author: Terry Weissman
- * weissman@sgi.com
- */
-
-
-
- #include "seahaven.h"
- #include "auto.h"
-
- #include <sys/time.h> // For time()
- #include <malloc.h>
- #include <X11/cursorfont.h>
-
- #include <math.h> // For random()
-
- Stack playstack[NUMPLAYSTACK];
- Stack singlestack[NUMSINGLESTACK];
- Stack donestack[NUMSUITS];
-
-
- static Stack allstacks[100];
- static int numstacks = 0;
-
- static int initializing = False;
- static int undoing = False;
-
- class StackPlayRec : public StackRec {
- public:
- StackPlayRec(int x, int y);
- virtual Bool addCard(Card, AnimType animate = Normal);
- virtual StackType getType();
- private:
- };
-
-
- class StackSingleRec : public StackRec {
- public:
- StackSingleRec(int x, int y);
- virtual Bool addCard(Card, AnimType animate = Normal);
- virtual StackType getType();
- private:
- };
-
-
- class StackDoneRec : public StackRec {
- public:
- StackDoneRec(int x, int y);
- virtual Bool addCard(Card, AnimType animate = Normal);
- virtual int getStackingHeight();
- virtual StackType getType();
- private:
- };
-
-
- UndoListRec::UndoListRec() {
- max = 100;
- cards = (Card *) malloc(max * sizeof(Card));
- stacks = (Stack *) malloc(max * sizeof(Stack));
- clear();
- }
-
-
- void UndoListRec::clear() {
- num = 0;
- }
-
- void UndoListRec::add(Card c, Stack s) {
- if (num >= max) {
- max += 100;
- cards = (Card *) realloc((char *) cards, max * sizeof(Card));
- stacks = (Stack *) realloc((char *) stacks, max * sizeof(Stack));
- }
- cards[num] = c;
- stacks[num] = s;
- num++;
- }
-
- void UndoListRec::addBoundary() {
- if (num > 0 && cards[num - 1] != NULL) add(NULL, NULL);
- }
-
-
- void UndoListRec::doUndo() {
- initializing = True; // Hack to fool StackPlayRec::addCard.
- if (num > 0 && cards[num - 1] == NULL) num--;
- while (num > 0 && cards[num - 1] != NULL) {
- num--;
- stacks[num]->addCard(cards[num]);
- }
- initializing = False;
- for (int i=0 ; i<NUMPLAYSTACK ; i++) playstack[i]->repositionAll();
- }
-
- Bool UndoListRec::isEmpty() {
- for (int i = 0 ; i<num ; i++) if (cards[i]) return False;
- return True;
- }
-
- UndoListRec undostack;
- UndoListRec redostack;
-
- void AddUndo(Card c, Stack s) {
- UndoList list = undoing ? &redostack : &undostack;
- list->add(c, s);
- }
-
-
- void UndoBoundary() {
- undostack.addBoundary();
- redostack.clear();
- }
-
-
- void DoUndo() {
- undoing = True;
- undostack.doUndo();
- undoing = False;
- redostack.addBoundary();
- }
-
- void DoRedo() {
- redostack.doUndo();
- undostack.addBoundary();
- }
-
-
- void DoRestart() {
- while (!undostack.isEmpty()) DoUndo();
- }
-
- StackRec::StackRec(int newx, int newy) {
- x = newx;
- y = newy;
- numcards = 0;
- allstacks[numstacks++] = this;
- }
-
- void StackRec::clear() {
- numcards = 0;
- }
-
- int StackRec::getX() {
- return x;
- }
-
- int StackRec::getY() {
- return y;
- }
-
- Card StackRec::getTopCard() {
- if (numcards == 0) return NULL;
- return cards[numcards - 1];
- }
-
- Card StackRec::getCardAbove(Card c) {
- int i;
- for (i=0 ; i<numcards - 1 ; i++) {
- if (cards[i] == c) return cards[i + 1];
- }
- return NULL;
- }
-
-
- static int Abs(int x) {
- return (x < 0) ? -x : x;
- }
-
-
- static int Max(int a, int b) {
- return (a > b) ? a : b;
- }
-
-
- void StackRec::repositionAll() {
- for (int i=0 ; i<numcards ; i++) {
- cards[i]->setLoc(x, y + i * getStackingHeight());
- }
- }
-
- Card StackRec::popCard() {
- if (numcards == 0) return NULL;
- numcards--;
- return cards[numcards];
- }
-
- Bool StackRec::addCard(Card c, AnimType animate) {
- if (c->getStack() == this) Punt("Error in StackRec::addCard!");
- if (animate == Animate) {
- c->raise();
- int oldx = c->getX();
- int oldy = c->getY();
- int newx = x;
- int newy = y + numcards * getStackingHeight();
- int numsteps = Max(Abs(oldx - newx), Abs(oldy - newy)) / speedup;
- float curx = (float) oldx;
- float cury = (float) oldy;
- for (int i = 0 ; i<numsteps ; i++) {
- curx += ((float) (newx - oldx)) / numsteps;
- cury += ((float) (newy - oldy)) / numsteps;
- c->setLoc((int) curx, (int) cury);
- XFlush(dpy);
- }
- }
- if (animate != DontMove) {
- if (numcards > 0) c->raiseAbove(cards[numcards - 1]);
- c->setLoc(x, y + numcards * getStackingHeight());
- if (inautoplay) XFlush(dpy);
- }
- Stack old = c->getStack();
- if (old && old->popCard() != c) {
- Punt("Couldn't find card in old stack in StackRec::addCard!");
- }
- AddUndo(c, c->getStack());
- c->setStack(this);
- cards[numcards++] = c;
- return True;
- }
-
-
- int StackRec::getStackingHeight() {
- return 34;
- }
-
- StackType StackRec::getType() {
- Punt("Invalid call to base class: StackRec::getType()");
- return Single;
- }
-
- StackPlayRec::StackPlayRec(int x, int y) : StackRec(x, y) {
- }
-
-
- Bool StackPlayRec::addCard(Card c, AnimType animate) {
- if (!initializing) {
- if (numcards == 0) {
- if (c->getValue() != NUMVALUES - 1) return False;
- } else {
- if (c->getSuit() != cards[numcards - 1]->getSuit() ||
- c->getValue() != cards[numcards - 1]->getValue() - 1)
- return False;
- }
- }
- return StackRec::addCard(c, animate);
- }
-
- StackType StackPlayRec::getType() {
- return Play;
- }
-
-
- StackSingleRec::StackSingleRec(int x, int y) : StackRec(x, y) {
- XSetWindowAttributes attributes;
- long valuemask = CWBackPixel | CWBorderPixel;
- attributes.background_pixel = GetColor("darkgreen", "grey70",
- WhitePixel(dpy, screen));
- attributes.border_pixel = GetColor("green", "grey90", BlackPixel(dpy, screen));
- Window w = XCreateWindow(dpy, toplevel, x - 1, y - 1,
- CARDWIDTH, CARDHEIGHT, 1, (int) CopyFromParent,
- InputOutput, (Visual *) CopyFromParent,
- valuemask, &attributes);
- XLowerWindow(dpy, w);
- XMapWindow(dpy, w);
- }
-
- StackSingleRec::addCard(Card c, AnimType animate) {
- if (numcards) return False;
- return StackRec::addCard(c, animate);
- }
-
- StackType StackSingleRec::getType() {
- return Single;
- }
-
-
- StackDoneRec::StackDoneRec(int x, int y) : StackRec(x, y) {
- }
-
- StackDoneRec::addCard(Card c, AnimType animate) {
- if (numcards == 0) {
- if (c->getValue() != 0) return False;
- } else {
- if (c->getSuit() != cards[numcards - 1]->getSuit() ||
- c->getValue() != cards[numcards - 1]->getValue() + 1)
- return False;
- }
- return StackRec::addCard(c, animate);
- }
-
- StackDoneRec::getStackingHeight() {
- return 0;
- }
-
- StackType StackDoneRec::getType() {
- return Done;
- }
-
-
- static int Random(int i) {
- return random() % i;
- }
-
-
-
- void AutoMoves() {
- Bool found;
- int i;
- do {
- found = False;
- for (i=0 ; i<numstacks ; i++) {
- Card card = allstacks[i]->getTopCard();
- if (card) {
- Card dcard = donestack[card->getSuit()]->getTopCard();
- if (card->getValue() == (dcard ? dcard->getValue() + 1 : 0)) {
- donestack[card->getSuit()]->addCard(card,
- inautoplay ? Normal
- : Animate);
- found = True;
- }
- }
- }
- } while (found);
- for (i=0 ; i<NUMSUITS ; i++) {
- Card card = donestack[i]->getTopCard();
- if (card == NULL ||
- donestack[i]->getTopCard()->getValue() < NUMVALUES - 1) return;
- }
- score->wonGame();
- }
-
-
- int NumAvailableSingles() {
- int result = 0;
- for (int i=0 ; i<NUMSINGLESTACK ; i++) {
- if (singlestack[i]->getTopCard() == NULL) result++;
- }
- return result;
- }
-
-
- Stack GetAvailableSingle() {
- for (int i=0 ; i<NUMSINGLESTACK ; i++) {
- if (singlestack[i]->getTopCard() == NULL) return singlestack[i];
- }
- return NULL;
- }
-
-
- Stack StackFromPoint(int x, int y) {
- Stack *checklist;
- int num;
- if (y < playstack[0]->getY() - 20) {
- checklist = singlestack;
- num = NUMSINGLESTACK;
- } else {
- checklist = playstack;
- num = NUMPLAYSTACK;
- }
- for (int i=0 ; i<num ; i++) {
- if (x >= checklist[i]->getX() - CARDWIDTH / 2 &&
- x < checklist[i]->getX() + CARDWIDTH / 2) return checklist[i];
- }
- return NULL;
- }
-
-
- void NewGame() {
- int i, j, k, w;
- if (score) {
- score->lostGame(); // Has no effect if wonGame() already called.
- score->newGame();
- }
- initializing = True;
- for (i=0 ; i<numstacks ; i++) {
- allstacks[i]->clear();
- }
- Card deck[NUMSUITS * NUMVALUES];
- i = 0;
- for (int s = 0 ; s < NUMSUITS ; s++) {
- for (int v = 0 ; v < NUMVALUES ; v++) {
- deck[i++] = cards[s][v];
- cards[s][v]->setStack(NULL);
- }
- }
- if (score) score->saveGameBegin();
- for (k=0 ; k<CARDSPERPLAYSTACK ; k++) {
- for (j=0 ; j<NUMPLAYSTACK ; j++) {
- w = Random(i);
- playstack[j]->addCard(deck[w]);
- if (score) score->saveGameCard(deck[w]);
- deck[w] = deck[--i];
- }
- }
- for (j=0 ; j<i ; j++) {
- singlestack[j + 1]->addCard(deck[j]);
- if (score) score->saveGameCard(deck[j]);
- }
- if (score) score->saveGameEnd();
- initializing = False;
-
- AutoMoves();
- undostack.clear();
- redostack.clear();
- }
-
-
-
- void LoadStacks(Card deck[52]) {
- int i, j, k, w;
- initializing = True;
- for (i=0 ; i<numstacks ; i++) {
- allstacks[i]->clear();
- }
- initializing = True;
- for (int s = 0 ; s < NUMSUITS ; s++) {
- for (int v = 0 ; v < NUMVALUES ; v++) {
- cards[s][v]->setStack(NULL);
- }
- }
- w = 0;
- for (k=0 ; k<CARDSPERPLAYSTACK ; k++) {
- for (j=0 ; j<NUMPLAYSTACK ; j++) {
- playstack[j]->addCard(deck[w++]);
- }
- }
- for (j=0 ; j<2 ; j++) {
- singlestack[j + 1]->addCard(deck[w++]);
- }
- initializing = False;
-
- AutoMoves();
- undostack.clear();
- redostack.clear();
- }
-
-
- class StackNoticeExitRec {
- public:
- StackNoticeExitRec() {}
- ~StackNoticeExitRec();
- };
-
-
- StackNoticeExitRec::~StackNoticeExitRec() {
- if (score->getGameWonOrLost()) NewGame(); // Force save.
- }
-
-
- StackNoticeExitRec noticeexit;
-
- void StackInit() {
- int i;
- srandom(int(time(NULL)));
-
- for (i=0 ; i<NUMPLAYSTACK ; i++) {
- playstack[i] = new StackPlayRec(i * 72 + 10, 114);
- }
- for (i=0 ; i<NUMSINGLESTACK ; i++) {
- singlestack[i] = new StackSingleRec(i * 72 + 226, 10);
- }
- donestack[0] = new StackDoneRec(10, 10);
- donestack[1] = new StackDoneRec(82, 10);
- donestack[2] = new StackDoneRec(586, 10);
- donestack[3] = new StackDoneRec(658, 10);
- }
-
-
-
-
- void DoAutoPlay() {
- static Cursor waitcursor = NULL;
- if (waitcursor == NULL) waitcursor = XCreateFontCursor(dpy, XC_watch);
- XDefineCursor(dpy, toplevel, waitcursor);
- DoRestart();
- XFlush(dpy);
- inautoplay = True;
- int solvable = AutoPlay();
- if (solvable) {
- score->lostGame();
- score->setMessage("Solvable.");
- while (solutionhead) {
- SolutionLog temp = solutionhead;
- solutionhead = solutionhead->next;
- Card card = cards[temp->suit][temp->rank];
- if (temp->dest == -999) {
- AutoMoves();
- UndoBoundary();
- } else if (temp->dest == -99) {
- GetAvailableSingle()->addCard(card);
- } else if (temp->dest <= NUMPLAYSTACK) {
- playstack[temp->dest - 1]->addCard(card);
- } else {
- if (temp->rank == NUMVALUES - 1) { // King to empty stack.
- for (int i=0 ; i<NUMPLAYSTACK ; i++) {
- if (playstack[i]->getTopCard() == NULL) {
- playstack[i]->addCard(card);
- break;
- }
- }
- } else {
- cards[temp->suit][temp->rank+1]->getStack()->addCard(card);
- }
- }
- delete temp;
- XFlush(dpy); // For debugging.
- }
- } else {
- score->wonGame();
- score->setMessage("Unsolvable.");
- }
- inautoplay = False;
- XUndefineCursor(dpy, toplevel);
- }
-