/*
 * init.c
 *
 * Initialisations for 3Dc engine and pieces.
 * Interface initialisation is external.
 */
/*

    3Dc, a game of 3-Dimensional Chess
    Copyright (C) 1995  Paul Hicks

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    E-Mail: paulh@euristix.ie
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/time.h>
#include "machine.h"
#include "3Dc.h"

int n3DcErr;
Piece *SQUARE_EMPTY, *SQUARE_INVALID;

stack *MoveStack; /* The history of moves */
Piece *Board[LEVELS][RANKS][FILES]; /* The board */
Piece *Muster[COLOURS][PIECES]; /* The list of pieces */
int titleCount[TITLES] =
{
  /* king     */ 1,
  /* queen    */ 1,
  /* bishop   */ 2,
  /* knight   */ 2,
  /* rook     */ 2,
  /* prince   */ 2,
  /* princess */ 2,
  /* abbey    */ 4,
  /* cannon   */ 4,
  /* galley   */ 4,
  /* pawn     */ 24
};

/*
 * This function sets up the board
 */
Global Boolean
Init3Dc(void)
{
  File x;
  Rank y;
  Level z;
  Colour bw;
  int count[COLOURS][TITLES] = {{0,0,0,0,0,0,0,0,0,0,0},
                                {0,0,0,0,0,0,0,0,0,0,0}};
  Title name;
  /* This structure is mainly for "obviousness"; it is entirely trivial */
  Title StartBoard[LEVELS][RANKS][FILES] =

  { /* The boards */
    { /* Bottom board */
      { galley,  cannon, abbey, prince, princess,abbey, cannon, galley},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      { galley,  cannon, abbey, prince, princess,abbey, cannon, galley},
    },
    { /* Middle board */
      {   rook, knight, bishop,   king,  queen, bishop, knight,   rook},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      {   rook, knight, bishop,   king,  queen, bishop, knight,   rook}
    },
    { /* Top board */
      { galley,  cannon, abbey, prince, princess,abbey, cannon, galley},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   none,   none,   none,   none,   none,   none,   none,   none},
      {   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn,   pawn},
      { galley,  cannon, abbey, prince, princess,abbey, cannon, galley},
    }
  }; /* StartBoard */

  for (z = 0; z < LEVELS; ++z)
    {
      bw = WHITE;
      for (y = 0; y < RANKS; ++y)
        {
          /* From the 4th rank on is black's half of the board */
          if (y == 4)
            bw = BLACK;

          for (x = 0; x < FILES; ++x)
            {
              name = StartBoard[z][y][x];
              if ((name != none)
                  /*
                   * this part of the conditional is unnecessary as
                   * there are no "unknown" variables
                   */
                  /*
                   * && (count[bw][name] < titleCount[name])
                   */
                  )
                {
                  Muster[bw][MusterIdx(name, count[bw][name])] = 
                    Board[z][y][x] =
                      PieceNew(name, x, y, z, bw);
                  (count[bw][name])++;
                }
            }
        }
    }

  /* That's the pieces done.  Now for the move stack */
  MoveStack = StackNew();

  /* Start the random number generator */
  srandom((unsigned)time(NULL));

  /*
   * And finally initialise the global variables:
   * these are really dynamic global identifiers, in that they
   * are read-only interfaces to various modules; kind of like
   * getopt()'s optind and optarg.
   */
  n3DcErr = 0;

  SQUARE_INVALID = (Piece *)malloc(sizeof(Piece));
  SQUARE_EMPTY = (Piece *)malloc(sizeof(Piece));
  if (!CHECK(SQUARE_INVALID != NULL) &&
      !CHECK(SQUARE_EMPTY != NULL))
    return FALSE; /* If there's no memory now there never will be.. */

  return TRUE;
}

