/*
Dotty V1.0 - The Dots Game (Les Petits Carreaux)
Copyright (C) 1998 François Pessaux (francois.pessaux@inria.fr)


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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/


#include <Common.h>
#include <System/SysAll.h>
#include <UI/UIAll.h>

#include "bool.h"
#include "pilrc.h"
#include "dots.h"
#include "protos.h"


extern unsigned char game_width ;
extern unsigned char game_height ;
extern unsigned char n_vertices, n_edges, n_cells ;
extern struct vertex *vertices ;
extern struct edge *edges ;
extern struct cell *cells ;
extern unsigned char remaining_cells ;
extern unsigned char nb_horizontal_edges ;
extern boolean human_turn ;
extern VoidHand  computer_bitmap_handle ;
extern VoidHand  human_bitmap_handle ;
extern unsigned char pilot_plays_first ;
extern unsigned char human_score ;
extern unsigned char pilot_score ;




/* Clears the game data without allocating it */
void clear_game (void)
{
  unsigned char i ;

  for (i = 0; i < n_vertices; i++) vertices[i].group = i ;
  for (i = 0; i < n_edges; i++) edges[i].drawn = FALSE ;
  for (i = 0; i < n_cells; i++) cells[i].owner = OWNER_NONE ;

  remaining_cells = n_cells ;

  human_score = 0 ;
  pilot_score = 0 ;

  if (pilot_plays_first) {
    human_turn = FALSE ;
    send_computer_play_event () ;
  }
  else
    human_turn = TRUE ;
}



/* Initialise data structure, don't do clear_game () work */
/* Stop any game alive */
void init_game_data (void)
{
  /* set global variables describing the game */
  n_vertices = (game_width+1) * (game_height + 1) ;
  n_edges = game_height * (game_width+1) + game_width * (game_height+1) ;
  n_cells = game_width * game_height ;
  nb_horizontal_edges = game_width * (game_height+1) ;
  /* Stop any current game */
  remaining_cells = 0 ;

  /* Define vertice */
  vertices = (struct vertex*) MemPtrNew (n_vertices * sizeof (struct vertex)) ;

  /* Define edges */
  edges = (struct edge*) MemPtrNew (n_edges * sizeof (struct edge)) ;
  { unsigned char edge_count = 0 ;
  unsigned char col, row, vrtx ;
  /* Horizontal edges */
  for (row = 0 ; row <= game_height; row++) {
    for (col = 0 ; col < game_width ; col++) {
      vrtx = row * (game_width + 1) + col ;
      edges[edge_count].v1 = vrtx ;
      edges[edge_count].v2 = vrtx + 1 ;
      edge_count++ ;
    }
  }
  /* Vertical edges */
  for (row = 0; row < game_height; row++) {
    for (col = 0; col <= game_width; col++) {
      vrtx = row * (game_width + 1) + col ;
      edges[edge_count].v1 = vrtx ;
      edges[edge_count].v2 = vrtx + game_width + 1 ;
      edge_count++ ;
    }
  }}

  /* Define cells */
  cells = (struct cell*) MemPtrNew (n_cells * sizeof (struct cell)) ;
  { unsigned char cell_count = 0 ;
  unsigned char col, row ;
  for (row = 0; row <game_height; row++) {
    for (col = 0; col <game_width; col++) {
      cells[cell_count].top = row * game_width + col ;
      cells[cell_count].bottom = cells[cell_count].top + game_width ;
      cells[cell_count].left = nb_horizontal_edges +
	                                   (row*(game_width+1) + col) ;
      cells[cell_count].right = cells[cell_count].left + 1 ;
      cell_count++ ;
    }
  }}
}



void InitApplication (void)
{
  struct dotprefs dotprefs ;
  LocalID db_id ;

  /* Try to load preferences */
  if (PrefGetAppPreferencesV10 (dotAppId, 0, &dotprefs,
				sizeof (struct dotprefs)))
    {
      game_width = dotprefs.pref_game_width ;
      game_height = dotprefs.pref_game_height ;
      pilot_plays_first = dotprefs.pref_pilot_plays_first ;
    }

  /* Loads bitmaps but don't lock them */
  human_bitmap_handle = DmGet1Resource ('Tbmp', bitmapHuman) ;
  computer_bitmap_handle = DmGet1Resource ('Tbmp', bitmapComputer) ;

  /* Try to load a saved game */
  db_id = DmFindDatabase (0, dotsStateName) ;
  if (db_id) {
    /* Yes a saved game exists */
    VoidPtr *record ;
    VoidHand handle ;
    DmOpenRef dots_db ;

    /* Read game dimensions */
    dots_db = DmOpenDatabase (0, db_id, dmModeReadOnly) ;
    /* Width */
    handle = DmGetRecord (dots_db, 0) ;
    record = MemHandleLock (handle) ;
    game_width = *((unsigned char*)record) ;
    MemHandleUnlock (handle) ;
    /* Height */
    handle = DmGetRecord (dots_db, 1) ;
    record = MemHandleLock (handle) ;
    game_height = *((unsigned char*)record) ;
    MemHandleUnlock (handle) ;
    /* Player turn */
    handle = DmGetRecord (dots_db, 2) ;
    record = MemHandleLock (handle) ;
    human_turn = *((boolean*)record) ;
    MemHandleUnlock (handle) ;

    /* Allocate game structures */
    init_game_data () ;

    /* Re-fills structures with saved game values */
    /* Vertices */
    handle = DmGetRecord (dots_db, 3) ;
    record = MemHandleLock (handle) ;
    MemMove ((struct vertex*)vertices, (struct vertex*)record,
	     n_vertices * sizeof (struct vertex)) ;
    MemHandleUnlock (handle) ;
    /* Edges */
    handle = DmGetRecord (dots_db, 4) ;
    record = MemHandleLock (handle) ;
    MemMove ((struct edge*)edges, (struct edge*)record,
	     n_edges * sizeof (struct edge)) ;
    MemHandleUnlock (handle) ;
    /* Cells */
    handle = DmGetRecord (dots_db, 5) ;
    record = MemHandleLock (handle) ;
    MemMove ((struct cell*)cells, (struct cell*)record,
	     n_cells * sizeof (struct cell)) ;
    MemHandleUnlock (handle) ;
    /* Remaining cells */
    handle = DmGetRecord (dots_db, 6) ;
    record = MemHandleLock (handle) ;
    remaining_cells = *((unsigned char*)record) ;
    MemHandleUnlock (handle) ;
    /* Close the database before closing it */
    DmCloseDatabase (dots_db) ;
    /* Remove the database */
    db_id = DmFindDatabase (0, dotsStateName) ;
    DmDeleteDatabase (0, db_id) ;
  }
  else {
  /* Just allocate game data structure from defaults */
  /* but don't start any game */
  init_game_data () ;
  }
}

