// This may look like C code, but it is really -*- C++ -*- /////////////////////////////////////////////////////////////////////////// // // AMIGA Minesweeper - Open window, init gadgets, ... // // (c) 1992 Hubert Feyrer (c9020@rrzc1.rz.uni-regensburg.de) // /////////////////////////////////////////////////////////////////////////// /* ** Diverse "C"-Header */ #define class _class #define template _template #define IntuitionBase IntuiBase #define GfxBase GraphBase extern "C" { # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include } #undef IntuitionBase #undef GfxBase #undef class #undef template /* ** C++-Header */ #include "mine.h" #include "field.h" #include #include //* //* (zu) VIELE globale Daten... //* IntuiBase *IntuitionBase=NULL; // Typ NICHT IntuitionBase!!! GraphBase *GfxBase=NULL; // Typ NICHT GfxBase!!! Library *GadToolsBase=NULL; NewWindow nwin={ 0,0,0,0,-1,-1,IDCMP_CLOSEWINDOW|IDCMP_GADGETUP| IDCMP_MOUSEBUTTONS,WFLG_CLOSEGADGET|WFLG_OTHER_REFRESH |WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_ACTIVATE|WFLG_RMBTRAP ,NULL,NULL,NULL,NULL,NULL,0,0,0,0,WBENCHSCREEN }; Window *win=NULL; Gadget *glist=NULL; VisualInfo *vinfo=NULL; Screen *scr=NULL; timerequest treq; // Für Spielzeit-Anfrage MsgPort *tport; // -"- ----"---- ---"--- int fxs=0; // field x size int fys=0; // field y size int X0; // linker Rand des Minenfeldes int Y0; // rechter Rand des Minenfeldes int win_w; // Breite des Spiel-Fensters int win_h; // Höhe des Spiel-Fensters char *argv0=NULL; // argv[0] NewGadget nnumgad={ -1,-1,-1,-1,NULL,NULL,1000,PLACETEXT_IN,NULL,NULL}; Gadget *numgad=NULL; // Textgadget, um Restminen anzuzeigen char tnumgad[5]; // minesleft NewGadget ntimegad={ -1,-1,-1,-1,NULL,NULL,1001,PLACETEXT_IN,NULL,NULL}; Gadget *timegad=NULL; // Um Spielzeit anzuzeigen char ttimegad[5]; // playtime NewGadget ngogad={ -1,-1,-1,-1,NULL,NULL,1002,PLACETEXT_IN,NULL,NULL}; Gadget *gogad=NULL; // Restart-Button (nach Crash) TextFont *txtfont; // mit setfont eingestellter Font int countdown; // Restliche Felder int minesleft; // Anzahl unentdeckter Minen Offset validfields[]={ {-1,-1}, { 0,-1}, { 1,-1}, {-1, 0}, { 1, 0}, {-1, 1}, { 0, 1}, { 1, 1} }; //* //* Resourcen freigeben und Programm beenden. //* void shutdown(int rc, char *msg=NULL) { if(treq.tr_node.io_Message.mn_ReplyPort) CloseDevice((IORequest *)&treq); if(tport) DeletePort((MsgPort *)tport); if(win) CloseWindow(win); if(glist) FreeGadgets(glist); if(minefield){ for(int i=0;iActiveScreen; UnlockIBase(lock); txtfont=(TextFont *)OpenFont(scr->Font); // Mit c:setfont festge- // legter Zeichensatz fxs=2*txtfont->tf_XSize; if(scr->ViewPort.Modes&~LACE==0) fxs*=2; // LoRes fys=txtfont->tf_YSize+3; CloseFont(txtfont); X0=1.5*fxs; Y0=3*fys; win_w=X0+(1.5*fxs)+(lenx*fxs); win_h=Y0+fys+(leny*fys); // Gadgets initialisieren vinfo=GetVisualInfo(scr,TAG_END); if(vinfo==NULL){ shutdown(20,"Can't GetVisualInfo()!"); } Field::lastgad=CreateContext(&glist); if( Field::lastgad==NULL ){ shutdown(20,"Can't CreateContext()!"); } // Minenfeld errichten countdown=0; minefield=new Field **[lenx]; for(i=0;iFont; nnumgad.ng_LeftEdge = fxs; nnumgad.ng_TopEdge = 1.45*fys; nnumgad.ng_Width = 2.8*fxs; nnumgad.ng_Height = fys; Field::lastgad=numgad=CreateGadget(TEXT_KIND,Field::lastgad,&nnumgad, GTTX_Text,tnumgad, GTTX_Border, 2, TAG_END); if(numgad==NULL) shutdown(20,"Can't create numgad!"); // Zeitanzeige-Gadget sprintf(ttimegad,"%04d",playtime); ntimegad.ng_VisualInfo = vinfo; ntimegad.ng_TextAttr = scr->Font; ntimegad.ng_Width = 2.8*fxs; ntimegad.ng_Height = fys; ntimegad.ng_LeftEdge = win_w-(fxs+ntimegad.ng_Width); ntimegad.ng_TopEdge = 1.45*fys; Field::lastgad=timegad=CreateGadget(TEXT_KIND,Field::lastgad,&ntimegad, GTTX_Text,ttimegad, GTTX_Border, 2, TAG_END); if(numgad==NULL) shutdown(20,"Can't create timegad!"); // Restart-Button ngogad.ng_VisualInfo = vinfo; ngogad.ng_TextAttr = scr->Font; ngogad.ng_GadgetText = "Go!"; ngogad.ng_Width = ntimegad.ng_LeftEdge-floor(5.4*fxs); ngogad.ng_LeftEdge = 4.6*fxs; ngogad.ng_TopEdge = 1.45*fys; ngogad.ng_Height = fys; Field::lastgad=gogad=CreateGadget(BUTTON_KIND,Field::lastgad,&ngogad, TAG_END); // gogad->Flags |= GFLG_DISABLED; if(gogad==NULL) shutdown(20,"Can't create gogad!"); // Fenster aufmachen nwin.Width = win_w; nwin.Height = win_h; nwin.LeftEdge = (scr->Width-win_w)/2; nwin.TopEdge = (scr->Height-win_h)/2; nwin.Title = WIN_T; if(nwin.LeftEdge<=0 || nwin.TopEdge<=0) shutdown(20,"Choose smaller dimension or font!"); nwin.FirstGadget = glist; win=OpenWindowTags(&nwin,TAG_END); if(win==NULL) shutdown(20,"Can't open window!"); // Timer-Device öffnen und Uhr initialisieren tport=CreatePort("Mine timer-port",0); if(tport==NULL) shutdown(20,"Can't create timer-port!"); if(OpenDevice("timer.device",UNIT_VBLANK,(IORequest *)&treq,0)) shutdown(20,"No timer.device?!?"); treq.tr_node.io_Message.mn_ReplyPort = tport; treq.tr_node.io_Command = TR_ADDREQUEST; treq.tr_node.io_Flags = 0; treq.tr_node.io_Error = 0; treq.tr_time.tv_secs = 1; // 1 Sekunde warten treq.tr_time.tv_micro = 0; playtime=0; return; } //* //* Felder aufdecken, Minen anzeigen //* void showmines(void) { for(int i=0;iopen(1); } } } //* //* Felder zuschütten, Markierung löschen //* void removemines(void) { for(int i=0;iclear(); } } RefreshGadgets(glist,win,NULL); } //* //* Anzahl der Nachbarminen bei freien Feldern errechnen //* void calc_cnt(void) { for(int j=0;jcnt()!=-1){ int no=0; // Anzahl Minen in angrenzenden Feldern // Umgebung jedes einzelnen Feldes absuchen for(int v=0;v<8;v++){ int vi=i+validfields[v].dx; int vj=j+validfields[v].dy; if(inminefield(vi,vj)){ if(minefield[vi][vj]->cnt()==-1){ no++; } } } minefield[i][j]->cnt(no); } } } } //* //* Liefert Zufallszahl in [0;high) mit Algorithmus aus libg++ //* int rnd(int high) { static MLCG gen(0,(long)time(NULL)); static RandomInteger r(0,65535,&gen); return int(r.asLong(long(high-1))); } //* //* Minenfeld zu p Prozent verminen und Anzahl Minen in //* Nachbarfeldern berechnen lassen. //* void hidemines(int p) { int n=(lenx*leny*p)/100.0; // Anzahl zu legender Minen minesleft=n; while(n){ int x=rnd(lenx); int y=rnd(leny); if(minefield[x][y]->cnt()==-1) continue; minefield[x][y]->cnt(-1); --n; } calc_cnt(); }