/* Test a solution to FourCheeseStools.c */
#include "FourCheeseStools.h"
#include "intStack.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

intStack A, B, C, D; /* global, want access from several functions */
boolean setUpStacks(int capacity);
void printGame();
boolean validMove(move_t currentMove);
boolean validGame();

int main()
{
    int i, moveCount = 0, movesPredicted,
      numCheeses; /* loop index */
    move_t *myMoves;

    /*
     * get a list of moves and the number
     * of cheeses to be moved, and set up
     * stacks to simulate moves
     *
     */
    printf("Enter a positive number of cheeses: ");
    scanf("%d", &numCheeses);
    myMoves = moveList(numCheeses, 'A', 'D', 'B', 'C');
    setUpStacks(numCheeses);

    /* Check each move in the list */
    for (i = 0; myMoves[i].fromStool != '\0' ||
	     myMoves[i].toStool != '\0'; i++) {
	if (!validMove(myMoves[i])) {
	    printGame();
	    return 0;
	}
	moveCount++;
	/* printGame(); */
    }

    /* Check the final position */
    if (!validGame()) {
      printf("Unfinished game:\n");
      printGame();
      return 0;
    }

    /* done with the stacks */
    destroy(&A);
    destroy(&B);
    destroy(&C);
    destroy(&D);

    movesPredicted = fourStoolMove(numCheeses).moves;
    if (movesPredicted != moveCount) {
      printf("You predicted %d moves, but took %d\n",
	     movesPredicted, moveCount);
      return 0;
    }

    /* done with myMoves */
    free (myMoves);
    /* otherwise okay */
    printf("OK\n");

    return 0;
}

boolean setUpStacks(int capacity) 
{
  int i; /* loop index */

  if (initialize(&A, capacity) &
      initialize(&B, capacity) &
      initialize(&C, capacity) &
      initialize(&D, capacity)) {
    for (i = capacity; i > 0; i--) {
      push(&A, i);
    }
    return TRUE;
  }
  return FALSE;
}

void printGame()
{
  printf("\nStack A:\n");
  printStack(&A);
  printf("\nStack B:\n");
  printStack(&B);
  printf("\nStack C:\n");
  printStack(&C);
  printf("\nStack D:\n");
  printStack(&D);
}

boolean validMove(move_t currentMove)
{
  intStack *fromStool, *toStool;
  intStack *getStack(char stoolLabel);

  /*
   * get the appropriate stacks
   *
   */
  fromStool = getStack(currentMove.fromStool);
  toStool = getStack(currentMove.toStool);

  /*
   * if the move is legal, simulate it.
   * otherwise say there's a problem.
   *
   */
  if (!empty(fromStool) &&
      !full(toStool) &&
      (empty(toStool) ||
       peek(fromStool) < peek(toStool))) {
    push(toStool, pop(fromStool));
    return TRUE;
  }else {
    printf("Problem moving %c->%c\n",
	   currentMove.fromStool,
	   currentMove.toStool);
    return FALSE;
  }
}

intStack *getStack(char stoolLabel)
{
  if (stoolLabel == 'A')
    return &A;
  else if (stoolLabel == 'B')
    return &B;
  else if (stoolLabel == 'C')
    return &C;
  else
    return &D;

}

boolean validGame()
{
  if (empty(&A) &&
      empty(&B) &&
      empty(&C) &&
      full(&D))
    return TRUE;
  else
    return FALSE;
}

