/*	######################################################################
	# little15.c - Ein kleines simples GEM-Spiel fr Zwischendurch
	# @(#) Programm:  LITTLE15.APP
	# @(#) Start:     02.11.1994
	# @(#) Version:   08.09.1995
	# @(#) Copyright: Dirk Hagedorn, In der Esmecke 9, D-59846 Sundern
	# @(#) Kostenlose Weitergabe erlaubt!
	######################################################################
	# 08.09.1995: Anpassungen an SysGem2, Ver”ffentlichung des Quelltextes
	######################################################################	*/

#ifndef		RSC_INCLUDE
#define		RSC_INCLUDE	1				/* 1: Resource einbinden */
#endif


#ifdef __ENGLISH__
#define	RSC_NAME	"litt_eng.rsc"
#define	RSC_H		"litt_eng.h"
#define	RSC_RH		"litt_eng.rh"
#define	RSC_RSH		"litt_eng.rsh"
#else
#define	RSC_NAME	"litt_ger.rsc"
#define	RSC_H		"litt_ger.h"
#define	RSC_RH		"litt_ger.rh"
#define	RSC_RSH		"litt_ger.rsh"
#endif

	
/*	######################################################################
	# Includes
	######################################################################	*/

#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<aes.h>
#include	<vdi.h>
#include	<time.h>
#include	<sys_gem2.h>

#include	RSC_H

#if RSC_INCLUDE
#include	RSC_RH
#include	RSC_RSH
#endif


/*	######################################################################
	# Resource
	######################################################################	*/

#if RSC_INCLUDE
#define	t_deskmenu		rs_trindex[T_DESKMENU]
#define	t_menu			rs_trindex[T_MENU]
#define	t_info			rs_trindex[T_INFO]
#define	t_auth			rs_trindex[T_AUTH]
#define	t_fair			rs_trindex[T_FAIR]
#define	t_imag			rs_trindex[T_IMAG]
#define	a_new_game		rs_frstr[A_NEW_GAME]
#define	a_no_window		rs_frstr[A_NO_WINDOW]
#define	a_no_dragdrop	rs_frstr[A_NO_DRAGDROP]
#define	a_quit			rs_frstr[A_QUIT]
#else
OBJECT	*t_deskmenu,
		*t_menu,
		*t_info,
		*t_auth,
		*t_fair,
		*t_imag;
char	*a_new_game,
		*a_no_window,
		*a_no_dragdrop,
		*a_quit;
#endif



/*	######################################################################
	# Makros
	######################################################################	*/
#define	accessory		(par.acc_entry>-1)


/*	######################################################################
	# Konstanten
	######################################################################	*/
/* Applikations-Strings wie Fenstertitel, Accessory-Name etc. */

char	*SUBTITLE=		"LITTLE15",				/* Iconify-Titel */
		*WINTITLE=		"Little 15",			/* Fenstertitel  */
		*APP_NAME=		"Little 15",			/* Programm-Name */
		*APP_VERSION=	"2.0",					/* Version       */
		*ACC_NAME=		"  Little 15 ",			/* ACC-Eintrag   */
		*APP_WIDMUNG=	"FšR ANDREA & MAREEN",	/* Widmung       */
		*HYPFILE=		"*:\\little15.hyp";		/* Hypertext     */

/* Anzahl an Grafiks„tzen in der RSC */
#define	IMAGESETS	2

/* Spielfeld-Breite und -H”he */
#define	WIDTH	4	
#define	HEIGHT	4

/* Zwischenraum zwischen Images und Fensterrand */
#define	BORDER	16


/* Der Wert des freien Feldes */
#define	ISFREE	HEIGHT*WIDTH

/* Makro zum Testen, ob ein Stein an der richtigen Stelle ist, */
/* also ob der Wert des Feldes mit dem Sollwert bereinstimmt  */
#define fieldsolved(y,x)	((y*WIDTH)+x+1)	

/* Applikations-ID und Fenster-IDs*/
#define	APP_ID				'LI15'	
#define	MAINID				'MAIN'
#define	INFOID				'INFO'
#define	AUTHID				'AUTH'
#define	FAIRID				'FAIR'

/* Sooft werden die Felder bei den verschiedenen */
/* Schwierigkeitsstufen durcheinandergewrfelt */
#define TIMES_VERY_EASY		10
#define TIMES_EASY			20
#define TIMES_MEDIUM		50
#define TIMES_DIFF			100
#define TIMES_VERY_DIFF		200


/* Hilfsmatrix mit Objektnamen aus little15.h */
static const int GAMEIMAGE[IMAGESETS][HEIGHT*WIDTH]=
{
	{	NUMB_01, NUMB_02, NUMB_03, NUMB_04,
		NUMB_05, NUMB_06, NUMB_07, NUMB_08,
		NUMB_09, NUMB_10, NUMB_11, NUMB_12,
		NUMB_13, NUMB_14, NUMB_15, NUMB_00
	},
	{	LETT_A, LETT_B, LETT_C, LETT_D, 
		LETT_E, LETT_F, LETT_G, LETT_H,
		LETT_I, LETT_J, LETT_K, LETT_L,
		LETT_M, LETT_N, LETT_O, LETT_0
	}
};



/*	######################################################################
	# Typen
	######################################################################	*/
typedef enum
{	L_VERY_EASY, L_EASY, L_MEDIUM, L_DIFFICULT, L_VERY_DIFFICULT
}	LEVEL;

typedef enum
{	IS_NUMBERS, IS_LETTERS
}	IMGSET;



/*	######################################################################
	# Variablen
	######################################################################	*/
PARAMETER	par;
BITBLK		*i_iconify, *dh_iconify;


static IMGSET		imgset;
static LEVEL		level;

/* Die Koordinaten des freien Feldes */
static int free_y, free_x;

/* Das Spielfeld als Matrix */
static int field[HEIGHT+1][WIDTH+1];

/* Breite und H”he der G_IMAGEs */
static int imgheight, imgwidth;

/* Koordinaten der Fenster */
static int x_main, y_main;
static int x_info, y_info;

/* Der Zeichenbereich des Spielfensters */
static RECT work;


/* MFDBs und Array fr das VDI */
MFDB mfdb_field, mfdb_screen;
int pxy[8], color[2];


/*	######################################################################
	#  Alertboxen
	######################################################################	*/
/*	----------------------------------------------------------------------
	<- TRUE: Programm beenden
	----------------------------------------------------------------------	*/
static BOOLEAN alert_quit ( void )
{
	return ( 1==Alert(ALERT_NORM, 1, a_quit) );
}	/* alert_quit */


/*	----------------------------------------------------------------------
	<- TRUE: Neues Spiel
	----------------------------------------------------------------------	*/
static BOOLEAN alert_new_game ( void )
{
	return ( 1==Alert(ALERT_NORM, 1, a_new_game) );
}	/* alert_new_game */


/*	----------------------------------------------------------------------
	Warnung, daž kein Fenster mehr zur Verfgung steht
	----------------------------------------------------------------------	*/
static void alert_no_window ( void )
{
	Alert(ALERT_NORM, 1, a_no_window);
}

/*	----------------------------------------------------------------------
	Warnung, daž Drag & Drop nicht untersttzt wird
	----------------------------------------------------------------------	*/
static void alert_no_dragdrop ( void )
{
	Alert(ALERT_NORM, 1, a_no_dragdrop);
}


/*	----------------------------------------------------------------------
	Warnung, daž RSC nicht geladen werden konnte
	----------------------------------------------------------------------	*/
#if (!RSC_INCLUDE)
static void alert_rsc_error ( void )
{
	Alert(ALERT_NORM, 1, "[3][RSC-Datei nicht gefunden!|RSC-file not found!][ [OK ]");
}	/*alert_rsc_error*/
#endif



/*	######################################################################
	# 
	# Info-Dialoge
	#
	######################################################################	*/

/*	######################################################################
	# Autor-Dialog
	######################################################################	*/
static void open_author ( void )
{
	char wintitle[256];

	GetText(t_auth, AUTH_TITLE, wintitle);
	SetFlags(t_auth, AUTH_TITLE, HIDETREE);	

	SetText(t_auth, AUTH_WIDMUNG, APP_WIDMUNG);
	DoDialog(t_auth, 0, wintitle);
	
}	/*open_author*/




/*	######################################################################
	# Fairware-Dialog
	######################################################################	*/
void open_fair ( void )
{
	char wintitle[256];

	GetText(t_fair, FAIR_TITLE, wintitle);
	SetFlags(t_fair, FAIR_TITLE, HIDETREE);	

	DoDialog(t_fair, 0, wintitle);

}	/*open_fair*/


int handle_info (int msg, int button, DIALOG_INFO *inf)
{
	char s[32];
	
	switch (msg)
	{
		case SG_KEY:
			return(SG_KEYCONT);

		case SG_NOWIN:
			break;

		case SG_START:
			LinkImage(inf->id, dh_iconify, "INFO");
			sprintf(s, "VERSION %s (%s)", APP_VERSION, __DATE__);
			SetText(t_info, INFO_VERSION, s);
			break;

		case SG_POSX:	x_info= button;	break;
		case SG_POSY:	y_info= button;	break;
		
		case SG_QUIT:
			return (SG_CONT);
			
		case SG_END:
			switch (button)
			{
				case -1:
				case INFO_OK:
					return (SG_CLOSE);
				case INFO_LEGAL:
					open_fair();
					break;
				case INFO_AUTHOR:
					open_author();
					break;
			}
			break;
		case SG_DRAGDROP:
			alert_no_dragdrop();
			break;
	}
	
	return (SG_CONT);

} /*handle_info*/


void open_info ( void )
{
	char wintitle[256];

	GetText(t_info, INFO_TITLE, wintitle);
	SetFlags(t_info, INFO_TITLE, HIDETREE);	

	WindowDialog(
		INFOID,				/* ID         */
		x_info, y_info,		/* Position   */
		wintitle,			/* Titel      */
		"",					/* Info       */
		TRUE,				/* Closer?    */
		FALSE,				/* modal?     */
		t_info,				/* Objektbaum */
		NULL,				/* Menzeile  */
		0,					/* Editfeld   */
		NULL,				/* Userzeiger */
		handle_info			/* Handler    */
	);

} /*open_info*/







/*	######################################################################
	# 
	# Das Spiel an sich
	#
	######################################################################	*/
/*	----------------------------------------------------------------------
	Ein Feld mittels VDI-Funktionen zeichnen und ggf. die Maus ausschalten
	Kopieren des BITBLK eines G_IMAGE auf den Screen
	----------------------------------------------------------------------	*/
void draw_field (int y, int x, BOOLEAN mouseoff)
{
	int	obimg;
	
	if ( (x<0) || (y<0) || (x>WIDTH) || (y>HEIGHT) )
	{	return;
	}

	obimg= GAMEIMAGE[imgset][field[y][x]-1];

	mfdb_field.fd_addr= (void *) t_imag[obimg].ob_spec.bitblk->bi_pdata;
	
	pxy[4]= work.x + BORDER + x*imgwidth;
	pxy[5]= work.y + BORDER + y*imgheight;
	pxy[6]= pxy[4]+imgwidth-1;
	pxy[7]= pxy[5]+imgheight-1;

	if (mouseoff)	HideMouse();

	vrt_cpyfm(par.vdi_handle, MD_REPLACE, pxy, &mfdb_field, &mfdb_screen, color);

	if (mouseoff)	ShowMouse();
}	/* draw_field */



/*	----------------------------------------------------------------------
	Komplettes Spielfenster neu zeichnen.
	----------------------------------------------------------------------	*/
void redraw_game (WINDOW_INFO *inf)
{
	int x, y;

	work.x= inf->draw_area.x;
	work.y= inf->draw_area.y;
	
	HideMouse();
	for (y=0; y<HEIGHT; y++)
	{	for (x=0; x<WIDTH; x++)
		{	draw_field(y, x, FALSE);
		}	
	}
	ShowMouse();

}	/* redraw_game */



/*	----------------------------------------------------------------------
	<- TRUE: Spiel gel”st
	----------------------------------------------------------------------	*/
static BOOLEAN game_solved ( void )
{
	int y, x;
	
	for (y=0; y<HEIGHT; y++)
	{	for (x=0; x<WIDTH; x++)
		{	if (field[y][x]!=fieldsolved(y,x))
			{	return(FALSE);
			}
		}
	}

	return (TRUE);
		
}	/*game_solved*/



/*	----------------------------------------------------------------------
	<- TRUE: Ein Feld wurde umbewegt
	----------------------------------------------------------------------	*/
static BOOLEAN move_field ( int y, int x, BOOLEAN draw )
{
	int hilf;

	/* Stimmen die Koordinaten? */	
	if ( (y<0) || (x<0) || (y>=HEIGHT) || (x>=WIDTH) )
	{	return(FALSE);
	}

	/* Liegt angeklicktes Feld neben dem freien Feld? */
	if	(	( (free_y==y) && ( (free_x==(x-1)) || (free_x==(x+1)) ) )
		||	( (free_x==x) && ( (free_y==(y-1)) || (free_y==(y+1)) ) )
		)
	{
		/* Feldinhalte tauschen */
		hilf= field[free_y][free_x];
		field[free_y][free_x]= field[y][x];
		field[y][x]= hilf;
		
		if (draw)
		{	draw_field(free_y, free_x, TRUE);
			draw_field(y, x, TRUE);
		}
	
		free_y= y;
		free_x= x;
		
		return(TRUE);
	}
	
	return (FALSE);
}	/*move_field*/




/*	----------------------------------------------------------------------
	init_game() initialisiert das Spiel und zeichnet es ggf.
	----------------------------------------------------------------------	*/
static void init_game ( BOOLEAN draw )
{
	int y, x, sooft, i, ry, rx;
	
	for (y=0; y<HEIGHT; y++)
	{	for (x=0; x<WIDTH; x++)
		{	field[y][x]= fieldsolved(y,x);
		}
	}
	
	free_y= HEIGHT-1;	/* Freies Feld liegt rechts unten */
	free_x= WIDTH-1;
	
	switch(level)
	{	case L_VERY_EASY:		sooft= TIMES_VERY_EASY;	break;
		case L_EASY:			sooft= TIMES_EASY;		break;
		case L_MEDIUM:			sooft= TIMES_MEDIUM;	break;
		case L_DIFFICULT:		sooft= TIMES_DIFF;		break;
		case L_VERY_DIFFICULT:	sooft= TIMES_VERY_DIFF;	break;
	}


	/* Spielfeld durcheinanderwrfeln je nach Level      */
	/* Dazu einfach ein paar Mal die Nachbarn des freien */
	/* Feldes umbewegen. Spiel ist immer l”sbar!         */

	for (i=0; i<sooft; i++)
	{	switch ( (rand() % 4) )
		{	case 0:		ry= free_y-1;	rx=free_x;	break;
			case 1:		ry= free_y+1;	rx=free_x;	break;
			case 2:		ry= free_y;		rx=free_x-1;	break;
			default:	ry= free_y;		rx=free_x+1;	break;
		}
		move_field(ry, rx, FALSE);
	}

	if (draw)
	{	RedrawWindow(GetHandle(MAINID));
	}
	
}	/*init_game*/




/*	----------------------------------------------------------------------
	Meneintr„ge anpassen
	----------------------------------------------------------------------	*/
static void check_menu ( void )
{
	menu_icheck(t_menu, M_NUMBERS, imgset==IS_NUMBERS);
	menu_icheck(t_menu, M_LETTERS, imgset==IS_LETTERS);

	menu_icheck(t_menu, M_VERY_EASY, level==L_VERY_EASY);
	menu_icheck(t_menu, M_EASY, level==L_EASY);
	menu_icheck(t_menu, M_MEDIUM, level==L_MEDIUM);
	menu_icheck(t_menu, M_DIFF, level==L_DIFFICULT);
	menu_icheck(t_menu, M_VERY_DIFF, level==L_VERY_DIFFICULT);
	
}	/*check_menu*/




/*	----------------------------------------------------------------------
	handle_game() wertet Aktionen im Dialog aus
	->	msg:	SysGem-Message
		inf:	Dialog-Informationen
	----------------------------------------------------------------------	*/
int handle_game (int msg, WINDOW_INFO *inf)
{
	BOOLEAN		quit_game= FALSE;
	LEVEL		oldlevel= level;
	IMGSET		oldset= imgset;
	int			fy, fx;
	
	/* Umlenken auf andere Messages, damit nicht alles */
	/* programmiert werden muž bzw. extra Routinen     */
	/* angelegt werde mssen. Man ist ja faul ;-)      */
	
	switch (msg)
	{
		case SG_END:	/* Closer auf Meneintrag "Beenden" umlenken */
			msg= SG_MENU;
			inf->mItem= M_QUIT;
			break;
		case SG_HELP:	/* HELP auf Meneintrag "Hilfe" umlenken */
			msg= SG_MENU;
			inf->mItem= M_HELP;
			break;
	}


	switch (msg)
	{
		case SG_NOWIN:	/* Kein Fenster mehr vorhanden -> Abbruch! */
			alert_no_window();
			return(SG_ABORT);

		case SG_START:	/* Fenster initialisieren, bevor es gezeichnet wurde */
			LinkImage(inf->id, i_iconify, SUBTITLE);
			init_game(FALSE);
			check_menu();
			break;

		case SG_QUIT:	/* Fenster wurde geschlossen */
			return (SG_CONT);

		case SG_KEY:	/* Tastendrcke weitergeben */
			return(SG_KEYCONT);

		case SG_MENU:	/* Meneintrag wurde ausgew„hlt */
			switch (inf->mItem)
			{
				case M_NEW:			init_game(TRUE);			break;
				case M_INFO:		open_info();				break;
				case M_HELP:		CallOnlineHelp("Main");		break;
				case M_QUIT:		quit_game= TRUE;			break;
				
				case M_NUMBERS:		imgset= IS_NUMBERS;			break;
				case M_LETTERS:		imgset= IS_LETTERS;			break;
				
				case M_VERY_EASY:	level= L_VERY_EASY;			break;
				case M_EASY:		level= L_EASY;				break;
				case M_MEDIUM:		level= L_MEDIUM;			break;
				case M_DIFF:		level= L_DIFFICULT;			break;
				case M_VERY_DIFF:	level= L_VERY_DIFFICULT;	break;
			}
			
			if ( (imgset!=oldset) || (level!=oldlevel) )
			{	check_menu();
			}

			break;
		
		case SG_SIZED:	/* Fenster wurde vergr”žert */
			break;
		
		case SG_MOVED:	/* Fenster wurde verschoben */
			work.x= inf->clip.x;
			work.y= inf->clip.y;
			break;

		case SG_LCLICK1:
		case SG_LCLICK2:	/* Es wurde ins Fenster geklickt */
			/* Koordinaten des angeklickten Feldes berechnen */
			fx= (inf->mx - work.x - BORDER) / imgwidth;
			fy= (inf->my - work.y - BORDER) / imgheight;

			/* Wurde das angeklickte Feld verschoben? */
			if (move_field(fy, fx, TRUE))
			{	/* Ja -> Ist das Spiel jetzt gel”st? */
				if ( game_solved() )
				{	/* Ja -> Neues Spiel starten? */
					if ( alert_new_game() )
					{	/* Ja -> Fenster neu initialisieren */
						init_game(TRUE);
					}
					else
					{	/* Nein -> Spiel beenden */
						quit_game= TRUE;
					}
				}
			}
			break;
			
		case SG_DRAGDROP:
			alert_no_dragdrop();
			break;
	}


	if (quit_game)
	{	return (SG_TERM);
	}

	return (SG_CONT);

} /*handle_game*/




/*	----------------------------------------------------------------------
	open_game() ”ffnet das Spiel-Fenster
	----------------------------------------------------------------------	*/
static BOOLEAN open_game ( void )
{
	int handle;
	
	if ( (handle=GetHandle(MAINID))>0 )
	{	TopWindow(handle);
		return(TRUE);
	}
	
	handle= OpenWindow(
				MAINID,						/* id */
				"|Little 15",				/* name */
				"",							/* info */
											/* flags */
				CLOSER | NAME | MOVER | SMALLER,
				t_menu,						/* menu */
				8,							/* align */
				TRUE,						/* part_redraw */
				1, 							/* scroll_x */
				1,							/* scroll_y */
				WIDTH*imgwidth+BORDER*2,	/* doc_x */
				HEIGHT*imgheight+BORDER*2,	/* doc_y */
				0, 0,						/* x, y */
				WIDTH*imgwidth+BORDER*2,	/* w */
				HEIGHT*imgheight+BORDER*2,	/* h */
				NULL,						/* user */
				redraw_game,				/* redraw */
				handle_game					/* action */
			);

	if (handle<=0)
	{	alert_no_window();
		return(FALSE);
	}
	
	return(TRUE);

} /*open_game*/





/*	######################################################################
	#
	# Desktop-Men
	#
	######################################################################	*/
/*	----------------------------------------------------------------------
	handle_deskmenu() steuert die Desktop-Menzeile
	----------------------------------------------------------------------	*/
int handle_deskmenu ( int item )
{
	switch (item)
	{
		case DM_ABOUT:
			open_info();
			break;
		case DM_QUIT:
			return (SG_TERM);
	}
	
	return (SG_CONT);
}	/*handle_deskmenu*/



/*	----------------------------------------------------------------------
	handle_acc_open()
	----------------------------------------------------------------------	*/
void handle_acc_open ( void )
{
	open_game();
}	/*handle_acc_open*/



/*	----------------------------------------------------------------------
	handle_acc_close()
	----------------------------------------------------------------------	*/
void handle_acc_close ( void )
{
}	/*handle_acc_close*/




/*	----------------------------------------------------------------------
	handle_unknown()
	----------------------------------------------------------------------	*/
void handle_unknown ( int *msg )
{
	switch (*msg)
	{
		case 0x4711:	/* VA-Start */
			open_game();
			break;
	}
	
}	/*handle_unknown*/





/*	######################################################################
	#
	# Hauptroutine und Initialisierung
	#
	######################################################################	*/
/*	----------------------------------------------------------------------
	Zufallsgenerator mit Hilfe der Uhrzeit initialisieren
	----------------------------------------------------------------------	*/
static void init_rand ( void )
{
	time_t	zeit;
	struct	tm *clock;
	
	time(&zeit);
	clock = localtime(&zeit);
	srand( (clock->tm_hour)*100 + (clock->tm_min)*10 + (clock->tm_sec) );

}	/* init_rand */



/*	----------------------------------------------------------------------
	Grafikdaten initialisieren
	----------------------------------------------------------------------	*/
static void init_graphics ( void )
{
	imgwidth=	t_imag[NUMB_00].ob_spec.bitblk->bi_wb*8;
	imgheight=	t_imag[NUMB_00].ob_spec.bitblk->bi_hl;
	
	/* MFDB's initialisieren */
	memset( &mfdb_field, 0, sizeof(MFDB));
	mfdb_field.fd_w= imgwidth;
	mfdb_field.fd_h= imgheight;
	mfdb_field.fd_wdwidth= imgwidth/16;
	mfdb_field.fd_stand=  0;
	mfdb_field.fd_nplanes= 1;

	memset( &mfdb_screen, 0, sizeof(MFDB));

	/* Farbindizes fr vrt_cpyfm() */
	color[0]= 1;
	color[1]= 0;

	/* Quell-koordinaten fr vrt_cpyfm() */
	pxy[0]= 0;
	pxy[1]= 0;
	pxy[2]= imgwidth-1;
	pxy[3]= imgheight-1;
	

}	/*init_graphics*/


/*	----------------------------------------------------------------------
	Applikation initialisieren
	----------------------------------------------------------------------	*/
static void init_app ( void )
{
#if (!RSC_INCLUDE)
	/* Objektadressen ermitteln */
	t_deskmenu=		RscAdr(R_TREE, T_DESKMENU);
	t_menu=			RscAdr(R_TREE, T_MENU);
	t_info=			RscAdr(R_TREE, T_INFO);
	t_fair=			RscAdr(R_TREE, T_FAIR);
	t_auth=			RscAdr(R_TREE, T_AUTH);
	t_imag=			RscAdr(R_TREE, T_IMAG);
	a_new_game=		(char *) RscAdr(R_STRING, A_NEW_GAME);
	a_no_window=	(char *) RscAdr(R_STRING, A_NO_WINDOW);
	a_no_dragdrop=	(char *) RscAdr(R_STRING, A_NO_DRAGDROP);
	a_quit=			(char *) RscAdr(R_STRING, A_QUIT);
#endif

	/* Menzeilen anmelden */
	UseWindowMenu();
	InitMenuLine(t_deskmenu);
	InitMenuLine(t_menu);
	
	/* Dialoge anmelden, den Rckgabewert ignorieren wird einfach. */
	NewDialog(t_info);	
	NewDialog(t_fair);
	NewDialog(t_auth);


	/* Default-Koordinaten der Fenster setzen. */
	/* Bei [-1|-1] wird zentriert.             */
	x_main= -1;	y_main= -1;
	x_info= -1;	y_info= -1;
	
	/* Bitblocks der G_IMAGEs zum Ikonifizieren ermitteln */
	i_iconify= t_imag[IMG_ICONIFY].ob_spec.bitblk;
	dh_iconify= t_imag[IMG_DH].ob_spec.bitblk;

	/* Imageblock fr iconifiziertes anmelden */
	LinkMainImage(i_iconify, SUBTITLE);

	/* Onlinehilfe setzen */
	SetOnlineHelp("ST-GUIDE", "", HYPFILE);

	ShortCutColor(BLACK);			/* Schwarze Unterstriche  benutzen*/
	SetAlertTitle("");				/* Normale Alert-Boxen-šberschrift */

	/* Spiel-Defaults setzen */
	imgset= IS_NUMBERS;
	level= L_MEDIUM;
		
}	/*init_app*/




/*	----------------------------------------------------------------------
	main()
	<-	!=0:	ein Fehler ist aufgetreten
	----------------------------------------------------------------------	*/

/* Hier die Schlssel fr SysGem2 angeben */

#define	MY_KEY1			0x0L
#define	MY_KEY2			0x0L


int main ( void )
{
#if RSC_INCLUDE
	int i;		
#endif
	BOOLEAN rsc_loaded;

	if (InitGem(ACC_NAME, APP_ID, APP_NAME))
	{
		SetKey(MY_KEY1, MY_KEY2);
		GetParStruct(&par);
		
#if RSC_INCLUDE
		/* eingebundene Resource initialisieren */
		for (i=0; i<NUM_OBS; i++)
		{	rsrc_obfix (&rs_object[i], 0);
		}
		rsc_loaded= TRUE;
#else
		ShowBee();
		if ( LoadResource(RSC_NAME, FALSE)>=0 )
		{	rsc_loaded= TRUE;
			ShowArrow();
		}
		else
		{	rsc_loaded= TRUE;
			ShowArrow();
			if (!accessory)
			{	alert_rsc_error();
			}
		}
#endif

		if ( rsc_loaded )
		{	/* Unter MultiTOS Meneintrag setzen, wenn Programm */
			if ( (!accessory) && (par.aes_version>=0x0400) )
			{	menu_register(par.appl_id, ACC_NAME);
			}

			init_app();
			init_graphics();
			init_rand();
			
			if (accessory)
			{	SetAccProc(handle_acc_open, handle_acc_close);
				HandleSysGem();
			}
			else
			{	if (!par.multitask)
				{	SetDeskTopMenu(t_deskmenu, handle_deskmenu);
				}
				if (open_game())
				{	HandleSysGem();
				}
			}
		}
		else
		{	if (accessory)
			{	while (TRUE) evnt_timer(10000,0);
			}
		}
		ExitGem();
	}
	
	return (0);
	
}	/*main*/


/*	######################################################################
	# little15.c
	######################################################################	*/
