/* ###################################################################### # 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 #include #include #include #include #include #include #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) || (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 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=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 ###################################################################### */