/*- * Copyright (c) 2001 * Tatsuya Kudoh(CDR/TK),ROYALPANDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ /* ** Falling Tower KAI ** Copyright (c) 2000 ROYALPANDA All rights reserved ** ** May 25, 2000 Ver 1.0 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include"key.h" #include"xjump.h" #include"xjump_xlib.h" #include"record.h" #include"picture.xpm" #include"title.xpm" #include"icon.xbm" #include"icon_msk.xbm" /*********************************************************** ** ** Xt Intrinsic data ** ************************************************************/ typedef struct{ String up; String down; String left; String right; String trig1; String trig2; String trig3; String trig4; String pause; String quit; int private; String title_xpm; String graphic; } AppData; static AppData app_data; static XtResource Resources[] = { { "keyUp", "KeyUp", XtRString, sizeof(String), XtOffsetOf(AppData,up), XtRImmediate,"Up" }, { "keyDown", "KeyDown", XtRString, sizeof(String), XtOffsetOf(AppData,down), XtRImmediate,"Down" }, { "keyLeft", "KeyLeft", XtRString, sizeof(String), XtOffsetOf(AppData,left), XtRImmediate,"Left" }, { "keyRight", "KeyRight", XtRString, sizeof(String), XtOffsetOf(AppData,right), XtRImmediate,"Right" }, { "keyTrig1", "KeyTrig1", XtRString, sizeof(String), XtOffsetOf(AppData,trig1), XtRImmediate,"space" }, { "keyTrig2", "KeyTrig2", XtRString, sizeof(String), XtOffsetOf(AppData,trig2), XtRImmediate,"n" }, { "keyTrig3", "KeyTrig3", XtRString, sizeof(String), XtOffsetOf(AppData,trig3), XtRImmediate,"x" }, { "KeyTrig4", "KeyTrig4", XtRString, sizeof(String), XtOffsetOf(AppData,trig4), XtRImmediate,"c" }, { "keyPause", "KeyPause", XtRString, sizeof(String), XtOffsetOf(AppData,pause), XtRImmediate,"p" }, { "keyQuit", "KeyQuit", XtRString, sizeof(String), XtOffsetOf(AppData,quit), XtRImmediate,"q" }, { "private", "Private", XtRBoolean, sizeof(int), XtOffsetOf(AppData,private), XtRImmediate,(XtPointer)False }, { "titleXPM", "TitleXPM", XtRString, sizeof(String), XtOffsetOf(AppData,title_xpm), XtRImmediate,NULL }, { "graphicXPM", "GraphicXPM", XtRString, sizeof(String), XtOffsetOf(AppData,graphic), XtRImmediate,NULL }, }; static XrmOptionDescRec Options[] = { {"-up","*keyUp",XrmoptionSepArg,(caddr_t)NULL }, {"-down","*keyDown",XrmoptionSepArg,(caddr_t)NULL }, {"-left","*keyLeft",XrmoptionSepArg,(caddr_t)NULL }, {"-right","*keyRight",XrmoptionSepArg,(caddr_t)NULL }, {"-trig1","*keyTrig1",XrmoptionSepArg,(caddr_t)NULL }, {"-trig2","*keyTrig2",XrmoptionSepArg,(caddr_t)NULL }, {"-trig3","*keyTrig3",XrmoptionSepArg,(caddr_t)NULL }, {"-trig4","*keyTrig4",XrmoptionSepArg,(caddr_t)NULL }, {"-pause","*keyPause",XrmoptionSepArg,(caddr_t)NULL }, {"-quit","*keyQuit",XrmoptionSepArg,(caddr_t)NULL }, {"-private","*private",XrmoptionNoArg,(caddr_t)"True" }, {"+private","*private",XrmoptionNoArg,(caddr_t)"False" }, {"-title","*titleXPM",XrmoptionSepArg,(caddr_t)NULL }, {"-graphic","*graphicXPM",XrmoptionSepArg,(caddr_t)NULL }, }; static XtAppContext App; /* Application context */ static Widget Top; /* Toplevel */ static Widget Score; /* score (Label) */ static Widget Scr; /* main screen (core) */ static Widget Score_v; /* hiscore frame (viewport) */ static Widget ScoreList; /* hiscore (label) */ static Widget Gameover; /* gameover (label) */ static Widget Pause; /* pause (label) */ static Widget Message; /* message (label) */ static int IntervalState; /* Is timer running? */ static XtIntervalId IntervalId; /* timer ID */ extern char *DefaultResources[]; /****************************************************** ** ** Xlib data ** ******************************************************/ static Colormap Cmap; /* colormap */ static XKeyboardState Keyboard; static int Repeat_mode = 1; /* key repeat mode (1:default 0:off) */ Display *Disp; /* display */ GC Gc_nomask; /* GC for no masking */ GC Gc_mask; /* GC for masking */ /* drawables */ Drawable Scr_d; /* main screen */ Pixmap Char_p; /* characters */ Pixmap Char_m; /* characters(mask) */ Pixmap Floor_p[4]; /* floor */ /***************************************************** ** ** game data ** *****************************************************/ static int Sc; /* score */ static int State; /* State */ #define STATE_TITLE 0 #define STATE_GAME 1 #define STATE_GAMEOVER 2 #define STATE_PAUSE 3 #define TIC 20 /* tics */ static int Redraw_enable; /* recording */ static record_file_t Record; static record_file_t Record_private; static record_t My_record; static int Recording; static char User_dir[PATH_MAX]; static char Filename[3][PATH_MAX+1]; char *Myname; /* program name */ /************************************* ** ** prototypes ** *************************************/ static void timi( XtPointer c, XtIntervalId id ); /********************* ** message ** show message **********************/ void message( char *msg ) { XtVaSetValues(Message,XtNlabel,msg,NULL); } /************************************* ** ** local functions ** ************************************/ /******************************* ** repeat_off ** disable key repeat *******************************/ static void repeat_off( void ) { if( Repeat_mode ){ XGetKeyboardControl(Disp,&Keyboard); XAutoRepeatOff(Disp); Repeat_mode = 0; } } /****************************************** ** repeat_on ** reset key repeat mode as default ******************************************/ static void repeat_on( void ) { if( !Repeat_mode ){ if( Keyboard.global_auto_repeat ) XAutoRepeatOn(Disp); else XAutoRepeatOff(Disp); Repeat_mode = 1; } } /************************************* ** make_hiscore ** create hiscore list *************************************/ static void make_hiscore( void ) { struct tm *tm; time_t t; int i; char *p; record_t *q; char buf[80*(RECORD_ENTRY_PRIVATE+RECORD_ENTRY+7)]; if( !Recording ){ XtVaSetValues(ScoreList,XtNlabel, "Cannot save record file!", NULL); return; } p = buf; p += sprintf(p, "\n" "Rank Floor << Hi-Score Players >> Date\n" "---- ----- ------------------------------- " "----------------\n"); q = Record.record; for( i = 0 ; i < Record.num_record ; i++,q++ ){ t = q->date; tm = localtime(&t); p += sprintf(p, "%4d %4d %-31.31s %04d/%02d/%02d %02d:%02d\n", i+1,q->score,q->name, tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday, tm->tm_hour,tm->tm_min); } p += sprintf(p, "\n" "\n" "Rank Floor << Your Hi-Score >> Date\n" "---- ----- ------------------------------- " "----------------\n"); q = Record_private.record; for( i = 0 ; i < Record_private.num_record ; i++,q++ ){ t = q->date; tm = localtime(&t); p += sprintf(p, "%4d %4d %-31.31s %04d/%02d/%02d %02d:%02d\n", i+1,q->score,q->name, tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday, tm->tm_hour,tm->tm_min); } p--; *p = '\0'; XtVaSetValues(ScoreList,XtNlabel,buf,NULL); } /***************************************** ** put_score ** show score *****************************************/ static void put_score( void ) { char buf[32]; sprintf(buf,"%04d",Sc); XtVaSetValues(Score,XtNlabel,buf,NULL); } /***************************************** ** reset_timer ** disable interval timer *****************************************/ static void reset_timer( void ) { if( IntervalState ){ XtRemoveTimeOut(IntervalId); IntervalState = 0; } } /***************************************** ** set_timer ** enable interval timer *****************************************/ static void set_timer( void ) { if( IntervalState ) reset_timer(); IntervalId = XtAppAddTimeOut(App,TIC,(XtTimerCallbackProc)timi,NULL); IntervalState = 1; } /********************************************************** ** gameover ** transit to STATE_GAMEOVER **********************************************************/ static void gameover( void ) { XtMapWidget(Gameover); State = STATE_GAMEOVER; XFlush(Disp); My_record.score = Sc; My_record.date = time(NULL); } /********************************* ** title ** transit to STATE_TITLE *********************************/ static void title( void ) { reset_timer(); XtUnmapWidget(Gameover); XtUnmapWidget(Scr); State = STATE_TITLE; make_hiscore(); XtMapWidget(Score_v); } /******************************** ** start_game ** transit to STATE_GAME *********************************/ static void start_game( void ) { message(""); XtUnmapWidget(Score_v); XtUnmapWidget(Gameover); XtMapWidget(Scr); GAME_init(); Sc = 0; State = STATE_GAME; set_timer(); } /******************************************* ** pause_game ** toggle pause state ********************************************/ static void pause_game( void ) { switch( State ){ case STATE_GAME: reset_timer(); XtMapWidget(Pause); State = STATE_PAUSE; Redraw_enable = 1; break; case STATE_PAUSE: State = STATE_GAME; XtUnmapWidget(Pause); set_timer(); Redraw_enable = 0; break; } } /******************************************* ** quit_game ** quit game ********************************************/ static void quit_game(void ) { repeat_on(); XFlush( Disp ); exit(0); } /******************************** ** timi -- Xt interval timer handler ** interval timer handler ********************************/ static void timi( XtPointer c,XtIntervalId id ) { int floor; static int timer; int i; IntervalState = 0; set_timer(); switch( State ){ case STATE_GAME: floor = GAME_main(1); if( floor < 0 ){ gameover(); timer = 0; }else if( floor > Sc ){ Sc = floor; if( Sc > 9999 ) Sc = 9999; put_score(); } break; case STATE_GAMEOVER: if( timer++ < 1200 / TIC ){ GAME_main(0); break; } if( Recording ){ if( RECORD_write(&Record) < 0 || RECORD_write(&Record_private) < 0 ){ Recording = 0; } } title(); break; } } /*********************************************** ** focus -- Xt event handler ** change key repeat when focus is changed ***********************************************/ static void focus( Widget w,XtPointer p,XEvent *e ) { if( e->type == FocusIn ) repeat_off(); else repeat_on(); } /************************************************ ** expose -- Xt event handler ** redraw screen ***********************************************/ static void expose( Widget w,XtPointer p,XEvent *e ) { if( Redraw_enable && e->xexpose.count == 0 ) GAME_redraw(); } /************************************* ** key -- Xt event handler ** key press/release *************************************/ static void key( Widget w, XtPointer state, XEvent *e ) { int k; if( (int)state ){ k = KEY_change(e->xkey.keycode,1); if( k & KEY_QUIT ) quit_game(); else if( k & KEY_PAUSE ) pause_game(); }else{ k = KEY_change(e->xkey.keycode,0); if( State == STATE_TITLE && (k & (KEY_TRIG1|KEY_UP)) ){ start_game(); } } } /******************************************* ** sig_handler -- signal handler ** quit game ********************************************/ static void sig_handler( int dummy ) { quit_game(); } /********************************* ** set_icon ** set icon bitmap **********************************/ static void set_icon( void ) { Pixmap icon,mask; icon = XCreateBitmapFromData(Disp,DefaultRootWindow(Disp), icon_bits,icon_width,icon_height); mask = XCreateBitmapFromData(Disp,DefaultRootWindow(Disp), icon_msk_bits,icon_msk_width,icon_msk_height); XtVaSetValues(Top,XtNiconPixmap,icon,XtNiconMask,mask,NULL); } /************************** ** usage ** show usage ***************************/ static void usage() { fprintf(stderr,"Usage: %s [options]\n",Myname); fprintf(stderr,"\t-toolkitoption ...\n"); fprintf(stderr,"\t-private\t\tuse private colormap.\n"); fprintf(stderr,"\t-graphic 'file'\t\tuse your xpm graphic 'file'\n"); } /********************************* ** init_graphic ** initialize graphic data *********************************/ static void init_graphic( Pixmap *back, Pixmap *title, int *tw,int *th ) { int i,x; XpmAttributes attr; attr.valuemask = XpmColormap|XpmCloseness; attr.colormap = Cmap; attr.closeness = 40000; if( app_data.graphic != NULL ){ i = XpmReadFileToPixmap(Disp,DefaultRootWindow(Disp), app_data.graphic,&Char_p,&Char_m,&attr); }else{ i = XpmCreatePixmapFromData(Disp,DefaultRootWindow(Disp), picture_xpm,&Char_p,&Char_m,&attr); } if( i ){ fprintf(stderr,"%s: %s\n",Myname,XpmGetErrorString(i)); exit(1); } if( app_data.title_xpm != NULL ){ i = XpmReadFileToPixmap(Disp,DefaultRootWindow(Disp), app_data.title_xpm,title,NULL,&attr); }else{ i = XpmCreatePixmapFromData(Disp,DefaultRootWindow(Disp), title_xpm,title,NULL,&attr); } if( i ){ fprintf(stderr,"%s: %s\n",Myname,XpmGetErrorString(i)); exit(1); } *tw = attr.width; *th = attr.height; Gc_mask = XCreateGC(Disp,DefaultRootWindow(Disp),0,NULL); XSetClipMask(Disp,Gc_mask,Char_m); Gc_nomask = XCreateGC(Disp,DefaultRootWindow(Disp),0,NULL); *back = XCreatePixmap(Disp,DefaultRootWindow(Disp), WIDTH*16,16, DefaultDepth(Disp,DefaultScreen(Disp))); XCopyArea(Disp,Char_p,*back,Gc_nomask,80,128,16,16,0,0); XCopyArea(Disp,Char_p,*back,Gc_nomask,96,128,16,16,WIDTH*16-16,0); for( x = 16 ; x < WIDTH*16-16 ; x+=16 ) XCopyArea(Disp,Char_p,*back,Gc_nomask,0,128,16,16,x,0); for( i = 0 ; i < 3 ; i++ ){ Floor_p[i] = XCreatePixmap(Disp,DefaultRootWindow(Disp), WIDTH*16-32,16, DefaultDepth(Disp,DefaultScreen(Disp))); for( x = 0 ; x < WIDTH*16-32 ; x+=16 ){ XCopyArea(Disp,Char_p,Floor_p[i],Gc_nomask, i*16,128,16,16,x,0); } } Floor_p[3] = XCreatePixmap(Disp,DefaultRootWindow(Disp), WIDTH*16-32,16,DefaultDepth(Disp,DefaultScreen(Disp))); for( x = 0 ; x < WIDTH*16-32 ; x+=32 ){ XCopyArea(Disp,Char_p,Floor_p[3],Gc_nomask,48,128,32,16,x,0); } } /********** ** main **********/ int main( int argc, char **argv ) { Widget game,w; Pixmap back_p,title_p; int width,height; int i; int uid; #ifdef SETUID int euid; #endif Myname = argv[0]; if( Myname == NULL ) Myname = "xjumpx"; uid = getuid(); #ifdef SETUID euid = geteuid(); seteuid(uid); #endif XtSetLanguageProc(NULL,NULL,NULL); Top = XtVaAppInitialize(&App,"XJumpX",Options,XtNumber(Options), &argc,argv,DefaultResources,NULL); #ifdef SETUID seteuid(euid); #endif XtGetApplicationResources(Top,&app_data, Resources,XtNumber(Resources),NULL,0); Disp = XtDisplay(Top); if( app_data.private ){ Cmap = XCreateColormap(Disp,DefaultRootWindow(Disp), DefaultVisual(Disp,DefaultScreen(Disp)),AllocNone); XtVaSetValues(Top,XtNcolormap,Cmap,NULL); }else{ Cmap = DefaultColormap(Disp,DefaultScreen(Disp)); } if( argc > 1 ){ usage(); return 0; } KEY_init(); KEY_add(Disp,KEY_UP,app_data.up); KEY_add(Disp,KEY_LEFT,app_data.left); KEY_add(Disp,KEY_RIGHT,app_data.right); KEY_add(Disp,KEY_TRIG1,app_data.trig1); KEY_add(Disp,KEY_PAUSE,app_data.pause); KEY_add(Disp,KEY_QUIT,app_data.quit); init_graphic(&back_p,&title_p,&width,&height); game = XtVaCreateManagedWidget("game",formWidgetClass,Top,NULL); w = XtVaCreateManagedWidget("board",formWidgetClass,game,NULL); XtVaCreateManagedWidget("title",widgetClass,w, XtNwidth,width, XtNheight,height, XtNbackgroundPixmap,title_p, NULL); XtVaCreateManagedWidget("scLabel",labelWidgetClass,w,NULL); Score = XtVaCreateManagedWidget("score",labelWidgetClass,w, XtNlabel,"0000", NULL); Gameover = XtVaCreateManagedWidget("gameover",labelWidgetClass,game, XtNmappedWhenManaged,FALSE, NULL); Pause = XtVaCreateManagedWidget("pause",labelWidgetClass,game, XtNmappedWhenManaged,FALSE, NULL); Scr = XtVaCreateManagedWidget("scr",widgetClass,game, XtNwidth,WIDTH*16, XtNheight,HEIGHT*16, XtNmappedWhenManaged,FALSE, XtNbackgroundPixmap,back_p, NULL); Score_v = XtVaCreateManagedWidget("record_v",viewportWidgetClass,game, XtNwidth,WIDTH*16, XtNheight,HEIGHT*16, NULL); ScoreList = XtVaCreateManagedWidget("record",labelWidgetClass,Score_v, XtNlabel,"", NULL); Message = XtVaCreateManagedWidget("message",labelWidgetClass,game, XtNwidth,WIDTH*16, XtNlabel, "Copyright (C)2000 ROYALPANDA", NULL); XtAddEventHandler(Top,FocusChangeMask,FALSE,(XtEventHandler)focus,NULL); XtAddEventHandler(game,KeyPressMask,FALSE, (XtEventHandler)key,(XtPointer)1); XtAddEventHandler(game,KeyReleaseMask,FALSE, (XtEventHandler)key,(XtPointer)0); XtAddEventHandler(game,ExposureMask,FALSE, (XtEventHandler)expose,(XtPointer)0); if( signal(SIGINT,SIG_IGN) != SIG_IGN ) signal(SIGINT,sig_handler); if( signal(SIGTERM,SIG_IGN) != SIG_IGN ) signal(SIGTERM,sig_handler); XtRealizeWidget(Top); set_icon(); Scr_d = XtWindow(Scr); XFreePixmap(Disp,back_p); XFreePixmap(Disp,title_p); get_name(My_record.name,32,uid); My_record.uid = uid; Record.record_file = RECORD_FILE; Record.swap_file = SWAP_FILE; Record.lock_file = LOCK_FILE; Record.max_record = RECORD_ENTRY; Record.new_record = &My_record; Record.override = 1; sprintf(Filename[0],"%s/%d.dat",RECORD_DIR,uid); sprintf(Filename[1],"%s/%d.swap",RECORD_DIR,uid); sprintf(Filename[2],"%s/%d.lock",RECORD_DIR,uid); Record_private.record_file = Filename[0]; Record_private.swap_file = Filename[1]; Record_private.lock_file = Filename[2]; Record_private.max_record = RECORD_ENTRY_PRIVATE; Record_private.new_record = &My_record; Record_private.override = 0; if( RECORD_init(&Record) != -1 && RECORD_init(&Record_private) != -1 ){ Recording = 1; }else{ Recording = 0; } make_hiscore(); srnd(time(NULL)); State = STATE_TITLE; Redraw_enable = 0; XtAppMainLoop(App); return 0; }