home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
108.lha
/
Fragments.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-03-02
|
16KB
|
571 lines
/************************************************************************
**************************************************************************
** **
** Fragments.c **
** ----------- **
** **
** Auteur : Eric Le Saux **
** **
** Club Amiga Montreal (CAM) **
** C.P. 195 STATION "N" **
** Montreal (Quebec) **
** H2X 3M2, CANADA **
** **
** Date : 3 mars 1988 **
** **
** Statut : DOMAINE PUBLIC - Distribution non-commerciale seulement **
** PUBLIC DOMAIN - Freely redistributable **
** **
**************************************************************************
************************************************************************/
/*** Fichiers d'entetes *************************************************/
#include <stdio.h>
#include <ctype.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include <exec/memory.h>
/*** Fonctions et variables externes ************************************/
extern struct Library *OpenLibrary ();
extern struct TextFont *OpenFont ();
extern struct Screen *OpenScreen ();
extern struct Window *OpenWindow ();
extern struct IntuiMessage *GetMsg ();
extern APTR AllocMem ();
extern LONG AvailMem ();
extern int Enable_Abort;
/*** Quelques constantes ************************************************/
#define Largeur 640
#define Hauteur 400
#define Profond 1
#define MEM_SECURITE 30720L /* Memoire de securite, 30K */
/*** Variables globales pour le maintient du systeme ********************/
#define TriangleID 0
#define FragID 1
#define SortieID 2
SHORT BorderVectors0[] = {0,0,109,0,109,23,0,23,0,0};
struct Border Border0 = {-1,-1,1,0,JAM1,5,BorderVectors0,NULL};
struct IntuiText IText0 = {1,0,JAM2,39,7,NULL,(UBYTE *) "Base",NULL};
struct Gadget GadgTri = {NULL,32,77,108,22,NULL,RELVERIFY,BOOLGADGET,
(APTR)&Border0,NULL,&IText0,NULL,NULL,TriangleID,NULL};
SHORT BorderVectors1[] = {0,0,109,0,109,23,0,23,0,0};
struct Border Border1 = {-1,-1,1,0,JAM1,5,BorderVectors1,NULL};
struct IntuiText IText1 = {1,0,JAM2,2,7,NULL,(UBYTE *) "Fragmentation",NULL};
struct Gadget GadgFrag = {&GadgTri,32,50,108,22,NULL,RELVERIFY,BOOLGADGET,
(APTR)&Border1,NULL,&IText1,NULL,NULL,FragID,NULL};
SHORT BorderVectors2[] = {0,0,109,0,109,23,0,23,0,0};
struct Border Border2 = {-1,-1,1,0,JAM1,5,BorderVectors2,NULL};
struct IntuiText IText2 = {1,0,JAM2,29,7,NULL,(UBYTE *)"Sortie",NULL};
struct Gadget GadgSortie = {&GadgFrag,32,23,108,22,NULL,RELVERIFY,BOOLGADGET,
(APTR)&Border2,NULL,&IText2,NULL,NULL,SortieID,NULL};
#define GadgetList GadgSortie
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct TextAttr FonteAttr = { (UBYTE *) "topaz.font", 8, 0, 0 };
struct TextFont *Fonte;
struct Screen *Ecran;
struct NewScreen EcranData =
{
0,0,Largeur,Hauteur,Profond,
0,1,HIRES|LACE,CUSTOMSCREEN,&FonteAttr,
(UBYTE *) " Fragmentation de surfaces - Eric Le Saux - Club Amiga Montreal", NULL, NULL
};
struct Window *Fenetre;
struct NewWindow FenetreData =
{
0,12,Largeur,Hauteur-12,-1,-1,GADGETUP,
SIMPLE_REFRESH|BACKDROP|BORDERLESS|RMBTRAP,
NULL,NULL,NULL,NULL,NULL,0,0,0,0,CUSTOMSCREEN
};
/* NB: Les gadgets ne doivent pas etre linkes maintenant */
struct RastPort *RP;
/*** Structures de donnees ***/
struct Sommet
{
struct Sommet *Dr, *In; /* Voisins de droite et de dessous */
SHORT X,Y;
}
*Racine = NULL, /* Racine */
*Feuille1 = NULL, /* | */
*Feuille2 = NULL; /* v */
/* Feuille1 -> Feuille2 */
LONG Niveau = 0L; /* Niveau de fragmentation */
SHORT Ax, Ay; /* Amplitudes en X et en Y */
/*************************************************************************
**************************************************************************
**
** DetruitStructure ()
**
** Detruit la structure recursive de sommets.
**
*/
void DetruitStructure (S)
struct Sommet *S;
{
if (S->In)
{
DetruitStructure (S->In);
}
if (S->Dr)
{
S->Dr->In = NULL;
DetruitStructure (S->Dr);
}
FreeMem (S, (LONG)sizeof(*S));
}
/*************************************************************************
**************************************************************************
**
** Sortie ()
**
** Ferme ce qui a ete ouvert.
**
*/
void Sortie ()
{
if (Fenetre)
{
Move (RP, 34L, 111L);
Text (RP, "Deallocation.", 13L);
}
if (Racine) DetruitStructure (Racine);
if (Fenetre) CloseWindow (Fenetre);
if (Ecran) CloseScreen (Ecran);
if (IntuitionBase) CloseLibrary (IntuitionBase);
if (GfxBase) CloseLibrary (GfxBase);
if (Fonte) CloseFont (Fonte);
_exit (0L);
}
/*************************************************************************
**************************************************************************
**
** Erreur ()
**
** Affiche un message d'erreur a travers un requester.
** Laisse le choix entre l'abandon de la procedure et
** un autre essai.
**
** Si 'OnSort' est FALSE, on ne sort pas sur l'abandon, on renvoie
** le resultat de la requete.
*/
#define ErrGfxLib 0
#define ErrIntuiLib 1
#define ErrOpenWin 2
#define ErrOpenScr 3
#define ErrFonte 4
#define ErrMemoire 5
struct IntuiText Message = { 2, 1, JAM1, 17, 10, NULL, NULL, NULL };
struct IntuiText Essai = { 2, 1, JAM1, 5, 4, NULL, (UBYTE *) "Tentative", NULL };
struct IntuiText Abandon = { 2, 1, JAM1, 5, 4, NULL, (UBYTE *) "Abandon", NULL };
BOOL Erreur (Err,OnSort)
SHORT Err;
BOOL OnSort;
{
SHORT Resultat;
switch (Err)
{
case ErrGfxLib : Message.IText = (UBYTE *) "OpenLibrary: GfxLib";
break;
case ErrIntuiLib : Message.IText = (UBYTE *) "OpenLibrary: IntuiLib";
break;
case ErrOpenWin : Message.IText = (UBYTE *) "OpenWindow";
break;
case ErrOpenScr : Message.IText = (UBYTE *) "OpenScreen";
break;
case ErrFonte : Message.IText = (UBYTE *) "OpenFont: Topaz 8";
break;
case ErrMemoire : Message.IText = (UBYTE *) "Pas assez de memoire";
break;
default : Message.IText = (UBYTE *) "Erreur inconnue !";
break;
}
Resultat = AutoRequest (Fenetre, &Message, &Essai, &Abandon,
NULL, NULL, 300L, 60L);
if (Resultat || !OnSort) return (Resultat);
Sortie ();
}
/*************************************************************************
**************************************************************************
**
** Initialise ()
**
*/
void Initialise ()
{
/*=== La librairie Intuition ===*/
/*=== Si on n'a pas la bonne version, on ouvre celle presente pour ===*/
/*=== appeler la fonction AutoRequest (). ===*/
FOREVER
{
IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 33L); /* v1.2+ */
if (!IntuitionBase)
{
IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0L);
if (!IntuitionBase) Sortie (); /* Plus le choix ! */
Erreur (ErrIntuiLib,TRUE);
Sortie ();
}
else break;
}
/*=== La librairie graphique ===*/
FOREVER
{
GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0L);
if (!GfxBase) Erreur (ErrGfxLib,TRUE);
else break;
}
/*=== La ROMFonte par defaut ===*/
FOREVER
{
Fonte = OpenFont (&FonteAttr);
if (!Fonte) Erreur (ErrFonte,TRUE);
else break;
}
/*=== On ouvre l'ecran ===*/
FOREVER
{
Ecran = OpenScreen (&EcranData);
if (!Ecran) Erreur (ErrOpenScr,TRUE);
else break;
}
ShowTitle (Ecran, (LONG)FALSE);
/*=== On ouvre la fenetre ===*/
FenetreData.Screen = Ecran;
FOREVER
{
Fenetre = OpenWindow (&FenetreData);
if (!Fenetre) Erreur (ErrOpenWin,TRUE);
else break;
}
/*=== On pointe le RastPort de la fenetre ===*/
RP = Fenetre->RPort;
/*=== On assigne la fonte ===*/
SetFont (RP, Fonte);
}
/*************************************************************************
**************************************************************************
**
** _abort (), _cli_parse (), _wb_parse
**
*/
void _abort () { Sortie (); }
void _cli_parse () {}
void _wb_parse () {}
/*************************************************************************
**************************************************************************
**
** Rnd ()
**
** Retourne un nb dans un intervalle donne, bornes incluses.
** Le premier argument devrait etre plus petit que le second.
**
*/
USHORT Rnd (N1, N2)
USHORT N1, N2;
{
return ( ( ((rand()&0x00FF) * (N2-N1+1)) >> 8 ) + N1 );
}
/*************************************************************************
**************************************************************************
**
** Vibre ()
**
** Fait varier arg1 dans l'intervalle [arg1-arg2,arg1+arg2].
**
*/
SHORT Vibre (Moyenne, Etendue)
SHORT Moyenne, Etendue;
{
return ((SHORT)Rnd((USHORT)(Moyenne-Etendue),(USHORT)(Moyenne+Etendue)));
}
/*************************************************************************
**************************************************************************
**
** CreeSommet ()
**
** Cree dynamiquement un sommet et l'initialise.
**
*/
struct Sommet *CreeSommet (X,Y,D,I)
SHORT X, Y;
struct Sommet *D, *I;
{
struct Sommet *S;
S = (struct Sommet *) AllocMem ((LONG)sizeof(*S),MEMF_PUBLIC|MEMF_CLEAR);
if (S)
{
S->X = X;
S->Y = Y;
S->Dr = D;
S->In = I;
}
else Sortie (); /* Pas supposes se rendre ici */
return (S);
}
/*************************************************************************
**************************************************************************
**
** FragmenteStructure ()
**
** Fragmente la structure de sommets d'un niveau de plus.
** Si le Flag est true, on est au debut d'une rangee, et on peut descendre.
**
*/
void FragmenteStructure (S,Flag,Ax,Ay)
struct Sommet *S;
BOOL Flag;
SHORT Ax, Ay;
{
if (Flag && S->In->In) { FragmenteStructure (S->In,TRUE,Ax,Ay); }
if (S->Dr) { FragmenteStructure (S->Dr,FALSE,Ax,Ay); }
S->In->Dr = CreeSommet (Vibre((S->In->X+S->In->Dr->X)/2,Ax),
Vibre((S->In->Y+S->In->Dr->Y)/2,Ay),
S->In->Dr,
(S->In->In)?S->In->In->Dr:NULL);
S->In = CreeSommet (Vibre((S->X+S->In->X)/2,Ax),
Vibre((S->Y+S->In->Y)/2,Ay),
CreeSommet(Vibre((S->X+S->In->Dr->Dr->X)/2,Ax),
Vibre((S->Y+S->In->Dr->Dr->Y)/2,Ay),
(S->Dr)?S->Dr->In:NULL,
S->In->Dr),
S->In);
}
/*************************************************************************
**************************************************************************
**
** AfficheStructure ()
**
** Affiche la structure de sommets.
**
*/
void AfficheStructure (S,Flag)
struct Sommet *S;
BOOL Flag;
{
if (Flag && S->In->In) { AfficheStructure (S->In,TRUE); }
if (S->Dr) { AfficheStructure (S->Dr,FALSE); }
Move (RP, (LONG)S->X, (LONG)S->Y);
Draw (RP, (LONG)S->In->X, (LONG)S->In->Y);
Draw (RP, (LONG)S->In->Dr->X, (LONG)S->In->Dr->Y);
Draw (RP, (LONG)S->X, (LONG)S->Y);
}
/*************************************************************************
**************************************************************************
**
** InitStructure ()
**
** Initialisation de la structure de base : le triangle.
**
*/
void InitStructure ()
{
Racine = CreeSommet (0,0,NULL,NULL);
Feuille1 = CreeSommet (0,0,NULL,NULL);
Feuille2 = CreeSommet (0,0,NULL,NULL);
Racine->X = Largeur/2; Racine->Y = Hauteur/7;
Feuille1->X = Largeur/7; Feuille1->Y = Hauteur-Hauteur/5;
Feuille2->X = Largeur-Largeur/7; Feuille2->Y = Hauteur-Hauteur/5;
Racine->In = Feuille1;
Feuille1->Dr = Feuille2;
Ax = (Feuille2->X - Feuille1->X) / 3;
Ay = (Feuille2->Y - Racine->Y) / 4;
Niveau = 0L;
}
/*************************************************************************
**************************************************************************
**
** MemDesiree ()
**
** Retourne la quantite de memoire necessaire pour le prochain niveau.
** Plus la marge de securite pour le systeme : MEM_SECURITE.
**
*/
LONG MemDesiree (Niveau)
LONG Niveau;
{
LONG Puissance=1L, NbDeSommets;
while (Niveau--) Puissance *= 2L;
NbDeSommets = (Puissance) * (Puissance+1L) / 2L * 3L;
return ( NbDeSommets * ((LONG)sizeof(struct Sommet)+4L) + MEM_SECURITE);
}
/*************************************************************************
**************************************************************************
**************************************************************************
***
*** main ()
***
**/
main ()
{
struct IntuiMessage *Msg; /* Pointeur pour prendre les messages */
struct Gadget *Adresse; /* Pour noter l'adresse du gadget */
ULONG Secondes, Micros; /* Temps courant */
/*=== On permet l'abandon du programme ===*/
Enable_Abort = 1;
/*=== Init ===*/
Initialise ();
/*=== Au travail ! ===*/
CurrentTime (&Secondes, &Micros);
srand ( (SHORT) (Secondes&0x00FF) );
Rnd(0,0); Rnd(0,0); Rnd(0,0);
SetAPen (RP,1L);
/*=== Landscape ===*/
InitStructure ();
AfficheStructure (Racine,TRUE);
/*=== On attends un evenement: CTRL_C ou click de gadget. ===*/
FOREVER
{
AddGList (Fenetre, &GadgetList, 0L, -1L, NULL);
RefreshGadgets (&GadgetList, Fenetre, NULL);
if (Wait (1L<<Fenetre->UserPort->mp_SigBit|SIGBREAKF_CTRL_C) == SIGBREAKF_CTRL_C)
Sortie ();
RemoveGList (Fenetre, &GadgetList, -1L);
while (Msg = GetMsg (Fenetre->UserPort))
{
Adresse = (struct Gadget *) Msg->IAddress;
ReplyMsg (Msg);
if (Adresse->GadgetID == SortieID) Sortie ();
if (Adresse->GadgetID == TriangleID)
{
Move (RP, 34L, 111L); Text (RP, "Deallocation.", 13L);
DetruitStructure (Racine);
InitStructure ();
}
FOREVER
{
if ( AvailMem(MEMF_PUBLIC) < MemDesiree(Niveau) )
{
if (Erreur(ErrMemoire,FALSE)) continue;
else break;
}
else
{
Move (RP, 34L, 111L); Text (RP, "Fragmentation.", 14L);
FragmenteStructure (Racine,TRUE,Ax,Ay);
Ax /= 2; Ay /= 2; Niveau++;
SetRast (RP, 0L);
AfficheStructure (Racine,TRUE);
break;
}
}
}
}
}