// This may look like C code, but it is really -*- C++ -*-
///////////////////////////////////////////////////////////////////////////
//
//  AMIGA Minesweeper - Definition of the Field-object
//
//  (c) 1992 Hubert Feyrer (c9020@rrzc1.rz.uni-regensburg.de)
//
///////////////////////////////////////////////////////////////////////////

#define class _class
#define IntuitionBase IntuiBase
#define GfxBase GraphBase
extern "C" {
# include <stdio.h>
# include <exec/types.h>
# include <utility/tagitem.h>
# include <intuition/gadgetclass.h>
# include <libraries/gadtools.h>
# include <clib/gadtools_protos.h>
# include <clib/intuition_protos.h>
# include <clib/graphics_protos.h>
# include <ctype.h>
}    
#define IntuitionBase IntuitionBase
#define GfxBase GfxBase
#define class class

#include "mine.h"
#include "field.h"

Gadget *Field::lastgad=NULL;     // Wird in main() auf Ergebnis
                                 // von CreateContext() gesetzt!

//
// Klassendefinition für ein Feld des Mine-Programmes
//
Field::Field(int x, int y, int i, int j){
    static struct NewGadget ngad={
	-1,-1,-1,-1,                     /* x, y, w, h */
	NULL,                            /* ng_GadgetText */
	NULL,                            /* font */
	0,                               /* gadget-id */
	PLACETEXT_IN,                    /* flags */
	NULL,                            /* von GetVisualInfo() */
	NULL                             /* userdata */
      };
    
    ngad.ng_VisualInfo = vinfo;
    ngad.ng_TextAttr   = scr->Font;
    (ngad.ng_GadgetText = strcpy(txt," "))[0]=BLANK;
    ngad.ng_LeftEdge   = x;
    ngad.ng_TopEdge    = y;
    ngad.ng_Width      = fxs;
    ngad.ng_Height     = fys;
    
    lastgad=_gad=CreateGadget(BUTTON_KIND,lastgad,&ngad,TAG_END);
    if(_gad==NULL){
	fprintf(stderr,"Field::Field(%d,%d): Fehler in "
		"CreateGadget()!\n",x,y);
	shutdown(20);
    }
    
    _gad->Flags &= ~GFLG_SELECTED;
    _gad->UserData = (APTR)this;

    _cnt=0;            // Anzahl Nachbarminen; später!
    _open=0;           // nicht aufgedeckt
    _i=i;              // Spalte im minefield[][]
    _j=j;              // Zeile im minefield[][]
    countdown++;       // 1 Feld mehr zu erforschen
}

Field::~Field(void)
{
    // Nichts zu tun???
}

//*
//* Feld in Ausgangszustand versetzen
//*
void Field::clear(void)
{
    _open=0;
    _gad->Flags &= ~GFLG_SELECTED;
    _cnt=0;
    txt[0]=BLANK;
}


//*
//* Feld aufdecken
//*
void Field::open(int show=0)
{
    if(!_open){
	long pos = RemoveGadget(win,_gad);

	_open=1;
	if(show){
	    if(_cnt==-1){
		_gad->Flags &= ~GFLG_SELECTED;
		txt[0]=BOMB;
	    }else{
		_gad->Flags |= GFLG_SELECTED;
		if(!isdigit(txt[0])) txt[0]=BLANK;
	    }
	}else{
	    _gad->Flags |= GFLG_SELECTED;
	    switch(_cnt){
	      case -1:
		txt[0] = BOMB;
		break;
	      case  0: 
		txt[0] = BLANK;
		break;
	      default:
		txt[0] = NUM+_cnt;
	    }
	}
    
	AddGadget(win,_gad,pos);
	RefreshGList(_gad,win,NULL,1);
    }
}

//*
//* Feld überprüfen; force==1: auch markierte Felder
//*
GameStat Field::check(int force=0)
{
    if(txt[0]==BLANK || force){
	if(!_open){
	    if(_cnt==-1) return GAME_LOST;     // BUMM!
	    if(force && txt[0]==MARK && _cnt!=-1) minesleft++;
	    open();
	    if(_cnt==0){
		// rekursives check()en...
		for(int v=0;v<8;v++){
		    int vi=_i+validfields[v].dx;
		    int vj=_j+validfields[v].dy;
		    
		    if(inminefield(vi,vj)){
			Field *m=minefield[vi][vj];
			if(m->cnt()!=-1 && !m->_open){
			    // *** Rekursion *** //
			    minefield[vi][vj]->check(1);
			    
			    sprintf(tnumgad,"%04d",minesleft);
			    if(tnumgad[0]=='0') tnumgad[0]=' ';
			    GT_SetGadgetAttrs(numgad,win,NULL,
					      GTTX_Text,tnumgad,
					      TAG_END);
			}
		    }
		}
	    }
	    countdown--;        // 1 Feld weniger zum Sieg
	    if(countdown==0) return GAME_WON;
	}
    }
    return GAME_CONT;
}

GameStat Field::mark(void)
{
    if(!_open){
	char *t=txt;
	
	// Markierung setzen/löschen
	long pos = RemoveGadget(win,_gad);
	*t = (*t==BLANK)?MARK:BLANK;
	AddGadget(win,_gad,pos);
	RefreshGList(_gad,win,NULL,1);

	minesleft+=(*t==MARK)?-1:1;

	sprintf(tnumgad,"%04d",minesleft);
	if(tnumgad[0]=='0') tnumgad[0]=' ';
	GT_SetGadgetAttrs(numgad,win,NULL,
			  GTTX_Text,tnumgad,
			  TAG_END);
	
	RefreshGList(numgad,win,NULL,1);

	if(_cnt==-1){
	    if(*t==MARK)
	      countdown--;        // 1 Feld weniger zum Sieg...
	    else
	      countdown++;        // ...oder mehr!
	    
	    if(countdown==0) return GAME_WON;
	}
    }
    
    return GAME_CONT;
}
