/*
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 "pilrc.h"
#include "bool.h"
#include "dots.h"
#include "protos.h"


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



CustomPatternType dotted_pattern = {0x2481,0x8100,0x0081,0x8124} ;
/* Shift to add to coordonates to get centered on the screen */
short x_offset ;
short y_offset ;


/* Assumes that init_game_display has been called before */
void init_game_display (void)
{
  unsigned char x, y ;

  x_offset = (160 - (game_width * BLOCK_SIZE_X)) / 2 ;
  y_offset = TITLE_HEIGHT +
             (160-TITLE_HEIGHT - (game_height * BLOCK_SIZE_Y)) / 2 ;

  /* Clear screen (game zone) */
  { RectangleType rect = { 0, TITLE_HEIGHT, 160, 160 - TITLE_HEIGHT } ;
  WinEraseRectangle (&rect, 0) ;
  /* Clear score zone */
  rect.topLeft.x = 80 ; rect.topLeft.y = 1 ;
  rect.extent.x = 80 ; rect.extent.y = 12 ;
  WinEraseRectangle (&rect, 0) ; }

  WinSetPattern (dotted_pattern) ;
  for (x = 0; x < game_width; x++) {
    for (y = 0; y < game_height; y++) {
      /* Horizontal lines */
      WinFillLine ((x * BLOCK_SIZE_X) + 2 + x_offset,
		   (y * BLOCK_SIZE_Y) + y_offset,
		   ((x + 1) * BLOCK_SIZE_X) - 2 + x_offset,
		   (y * BLOCK_SIZE_Y) + y_offset) ;
      /* Vertical lines */
      WinFillLine ((x * BLOCK_SIZE_X) + x_offset,
		   (y * BLOCK_SIZE_Y) + 2 + y_offset,
		   (x * BLOCK_SIZE_X) + x_offset,
		   ((y + 1) * BLOCK_SIZE_Y) - 2 + y_offset) ;
    }
  }

  /* We must close the last line */
  for (x = 0; x < game_width; x++) {
    WinFillLine ((x * BLOCK_SIZE_X) + 2 + x_offset,
		 game_height * BLOCK_SIZE_Y + y_offset,
		 ((x + 1) * BLOCK_SIZE_X) - 2 + x_offset,
		 game_height * BLOCK_SIZE_Y + y_offset) ;
  }

  /* and the last column */
  for (y = 0; y < game_height; y++) {
    WinFillLine (game_width * BLOCK_SIZE_X + x_offset,
		 (y * BLOCK_SIZE_Y) + 2 + y_offset,
		 game_width * BLOCK_SIZE_X + x_offset,
		 ((y + 1) * BLOCK_SIZE_Y) - 2 + y_offset) ;
  }
}



/* x, y : cell's coord in the array, not in the screen */
/* Does nothing if the cell has no owner */
void cell_turn_on (unsigned char x, unsigned char y, unsigned char owner_flag)
{
  BitmapPtr  bitmap ;

  switch (owner_flag) {
  case OWNER_HUMAN:
    /* Human's cell */
    bitmap = MemHandleLock (human_bitmap_handle) ;
    WinDrawBitmap (bitmap,
		   (x * BLOCK_SIZE_X) + 2 + x_offset,
		   (y * BLOCK_SIZE_Y) + 2 + y_offset) ;
    MemHandleUnlock (human_bitmap_handle) ;
    break ;

  case OWNER_PILOT:
    /* Computer's cell */
    bitmap = MemHandleLock (computer_bitmap_handle) ;
    WinDrawBitmap (bitmap,
		   (x * BLOCK_SIZE_X) + 2 + x_offset,
		   (y * BLOCK_SIZE_Y) + 2 + y_offset) ;
    MemHandleUnlock (computer_bitmap_handle) ;
    break ;
  }
}




void edge_turn_on (unsigned char edge_num)
{
  unsigned char x, y ;
  RectangleType rect ;

  /* Erase old arrow (horizontal) */
  rect.topLeft.x = 0 ;
  rect.topLeft.y = y_offset - LEADING_SPACE - ARROW_HEIGHT ;
  rect.extent.x = 160 ;
  rect.extent.y = LEADING_SPACE + ARROW_HEIGHT ;
  WinEraseRectangle (&rect, 0) ;
  /* Erase old arrow (vertical) */
  rect.topLeft.x =  x_offset - LEADING_SPACE - ARROW_HEIGHT ;
  rect.topLeft.y = TITLE_HEIGHT ;
  rect.extent.x = LEADING_SPACE + ARROW_WIDTH ;
  rect.extent.y = 160 - TITLE_HEIGHT ;
  WinEraseRectangle (&rect, 0) ;

  if (edge_num >= nb_horizontal_edges) {
    /* Vertical edge */
    edge_num -= nb_horizontal_edges ;
    y = edge_num / (game_width + 1) ;
    x = edge_num % (game_width + 1) ;
    WinDrawLine (x * BLOCK_SIZE_X + x_offset,
		 (y * BLOCK_SIZE_Y) + 2 + y_offset,
		 x * BLOCK_SIZE_X + x_offset,
		 ((y + 1) * BLOCK_SIZE_Y) - 2 + y_offset) ;
    /* If computer played, we must update indocator arrows */
    if (! human_turn) {
      /* Draw new arrows */
      /* Vertical positionning */
      FntSetFont (4) ;
      WinDrawChars ("\003", 1, x_offset - LEADING_SPACE - ARROW_WIDTH,
		    y_offset + (y * BLOCK_SIZE_Y) + 3) ;
      /* Horizontal positionning */
      FntSetFont (5) ;
      WinDrawChars ("\002", 1,
		    x_offset + (x * BLOCK_SIZE_X) - 4,
		    y_offset - LEADING_SPACE - ARROW_HEIGHT) ;
    }
  }
  else {
    /* Horizontal edge */
    y = edge_num / game_width ;
    x = edge_num % game_width ;
    WinDrawLine ((x * BLOCK_SIZE_X) + 2 + x_offset,
		 y * BLOCK_SIZE_Y + y_offset,
		 ((x + 1) * BLOCK_SIZE_X) - 2 + x_offset,
		 y * BLOCK_SIZE_Y + y_offset) ;
    /* If computer played, we must update indocator arrows */
    if (! human_turn) {
      /* Draw new arrows */
      /* Vertical positionning */
      FntSetFont (4) ;
      WinDrawChars ("\003", 1,
		    x_offset - LEADING_SPACE - ARROW_WIDTH,
		    y_offset + (y * BLOCK_SIZE_Y) - 4) ;
      /* Horizontal positionning */
      FntSetFont (5) ;
      WinDrawChars ("\002", 1,
		    x_offset + (x * BLOCK_SIZE_X) + 3,
		    y_offset - LEADING_SPACE - ARROW_HEIGHT) ;
    }
  }

  /* Restore default font */
  FntSetFont (0) ;
}


void refresh_whole_game_display (void)
{
  unsigned char i, x, y ;

  for (i=0; i<n_edges; i++) if (edges[i].drawn) edge_turn_on (i) ;

  for (x = 0; x < game_width; x++) {
    for (y = 0; y < game_height; y++) {
      /* Let's reuse i instead of allocating a new variable... */
      i = cells[y*game_width+x].owner ;
      /* Update score */
      switch (i) { case OWNER_HUMAN: human_score++ ; break ;
                   case OWNER_PILOT: pilot_score++; break ; }
      cell_turn_on (x, y, i) ;
    }
  }
  /* Update score */
  display_score () ;
}
