diff options
Diffstat (limited to 'dash.c')
-rw-r--r-- | dash.c | 3400 |
1 files changed, 3400 insertions, 0 deletions
@@ -0,0 +1,3400 @@ +/* + + Simple boulder dash clone for X11/xlib/curses + + Needs a fast-ish machine - uses quite a few raster scans of the level + on each game cycle. + + ...And the curses/X pointer code could be neater and better thought out... + + ... It is only a hack though :-) ... + +*/ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xos.h> +#include <X11/Xatom.h> +#include <X11/keysym.h> + +#include <curses.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include <fcntl.h> +#include <pwd.h> +#include <math.h> +#include <signal.h> + +#include <stdarg.h> + +#include "Xbit.h" + +#define WINX 100 +#define WINY 100 +#define WINW 640 +#define WINH 400 + +#define RND(x) ((rand())%(x)) + +/* Slightly roundabout, but allows us to test the op +*/ +#ifdef NOUSLEEP +# define USLEEP(x) LocalUsleep(x) +#else +# define USLEEP(x) usleep(x) +#endif + +XSizeHints size_hints; +ulong black,white; +Display *disp; +Window window; +Colormap cm; +XFontStruct *font; + +char *GetPath(), + *GetFXPath(), + *GetLevelPath(), + *GetLibPath(); + +#define SPACESPRNAME "space" +#define EARTHSPRNAME "earth" +#define ROCKSPRNAME "rock" +#define ROCKFALLSPRNAME ROCKSPRNAME +#define TUFFWALLSPRNAME "tuffwall" +#define WALLSPRNAME "wall" +#define GEMSPRNAME "diamond" +#define GEMFALLSPRNAME GEMSPRNAME +#define HEROSPRNAME "miner" +#define EXITSPRNAME "exit" +#define BUTTSPRNAME "butterfly" +#define CHSRSPRNAME "chaser" +#define ROCKSWSPRNAME "rockswitch" +#define ONEUPSPRNAME "oneup" +#define FILTERSPRNAME "filter" +#define AMOEBASPRNAME "amoeba" +#define ROCKGENSPRNAME "rockgen" +#define BUTTGENSPRNAME "butterflygen" +#define CHSRGENSPRNAME "chasergen" + +#define SPACEGLY ' ' +#define EARTHGLY '.' +#define ROCKGLY '@' +#define TUFFWALLGLY '%' +#define WALLGLY '#' +#define GEMGLY '*' +#define HEROGLY 'R' +#define EXITGLY 'E' +#define BUTTGLY 'B' +#define CHSRGLY 'C' +#define ROCKSWGLY '!' +#define ONEUPGLY '&' +#define FILTERGLY '$' +#define AMOEBAGLY 'A' +#define ROCKGENGLY 'r' +#define BUTTGENGLY 'b' +#define CHSRGENGLY 'c' + +#define SPACESPR 0 +#define EARTHSPR 1 +#define ROCKSPR 2 +#define TUFFWALLSPR 3 +#define WALLSPR 4 +#define GEMSPR 5 +#define HEROSPR 6 +#define EXITSPR 7 +#define ROCKFALLSPR 8 +#define GEMFALLSPR 9 +#define BUTTSPR 10 +#define CHSRSPR 11 +#define ROCKSWSPR 12 +#define ONEUPSPR 13 +#define FILTERSPR 14 +#define AMOEBASPR 15 +#define ROCKGENSPR 16 +#define BUTTGENSPR 17 +#define CHSRGENSPR 18 +#define NOSPR 19 + +#define VOIDSPR -1 + +#define X(x) ((x)*chsz) +#define Y(y) ((y)*chsz) + +#define SCRX 40 +#define SCRY 24 + +typedef struct + { + char *name; + Pixmap p; + } sprite; + +sprite spr[NOSPR]= + { + {SPACESPRNAME,0}, + {EARTHSPRNAME,0}, + {ROCKSPRNAME,0}, + {TUFFWALLSPRNAME,0}, + {WALLSPRNAME,0}, + {GEMSPRNAME,0}, + {HEROSPRNAME,0}, + {EXITSPRNAME,0}, + {ROCKFALLSPRNAME,0}, + {GEMFALLSPRNAME,0}, + {BUTTSPRNAME,0}, + {CHSRSPRNAME,0}, + {ROCKSWSPRNAME,0}, + {ONEUPSPRNAME,0}, + {FILTERSPRNAME,0}, + {AMOEBASPRNAME,0}, + {ROCKGENSPRNAME,0}, + {BUTTGENSPRNAME,0}, + {CHSRGENSPRNAME,0} + }; + +char glyph_map[NOSPR]= + { + /* SPACESPR */ ' ', + /* EARTHSPR */ '.', + /* ROCKSPR */ '@', + /* TUFFWALLSPR */ '#', + /* WALLSPR */ '+', + /* GEMSPR */ '*', + /* HEROSPR */ '&', + /* EXITSPR */ 'E', + /* ROCKFALLSPR */ '@', + /* GEMFALLSPR */ '*', + /* BUTTSPR */ '%', + /* CHSRSPR */ '"', + /* ROCKSWSPR */ '^', + /* ONEUPSPR */ '$', + /* FILTERSPR */ '=', + /* AMOEBASPR */ '~', + /* ROCKGENSPR */ '+', + /* BUTTGENSPR */ '+', + /* CHSRGENSPR */ '+' + }; + +#define MAX_ENEMY 2000 +#define MAX_GENERATOR 100 + +typedef struct + { + int alive; + int type; + int x,y; + int dir; + int moved; + } Enemy; + +typedef struct + { + int cycle; + int type; + int x,y; + } Generator; + +Enemy enemy[MAX_ENEMY]; +Generator generator[MAX_GENERATOR]; +int no_enemy; +int no_generator; + + +#define AMOEBA_COUNT 5 + +typedef struct + { + int alive; + int count; + int size; + int could_move; + } Amoeba; + +Amoeba amoeba; +int max_amoeba_size; +int amoeba_move_chance; + + +#define WELLDONELEV -1 +#define TRYAGAINLEV -2 + +typedef struct + { + int sx,sy; + int ex,ey; + int x,y; + int time; + int no; + int toget; + int w,h; + char *name; + char *data; + } Level; + + +#define NONE -1 +#define UP 0 +#define RIGHT 1 +#define DOWN 2 +#define LEFT 3 + +#define ROT_RIGHT(d) ((((d)+1)>LEFT) ? (UP) : ((d)+1)) +#define ROT_LEFT(d) ((((d)-1)<UP) ? (LEFT) : ((d)-1)) +#define ROT_FLIP(d) (((d)+2)%4) + +struct + { + int x,y; + } move_tbl[4]= + { + {0,-1}, + {1,0}, + {0,1}, + {-1,0} + }; + +#define MAX_HISCORE 10 +#define HINAMELEN 32 + +typedef struct + { + int score; + char name[HINAMELEN+1]; + int level; + } hiscore; + +hiscore hisc[MAX_HISCORE]= + { + {10000,"Score 1",1}, + {9000,"Score 2",2}, + {8000,"Score 3",3}, + {7000,"Score 4",4}, + {6000,"Score 5",5}, + {5000,"Score 6",6}, + {4000,"Score 7",7}, + {3000,"Score 8",8}, + {2000,"Score 9",9}, + {1000,"Score 10",10} + }; + +int chsz=16; +int slp=-1; +int bw=False; +int startlev=1; +int cursesmode=False; + +double si[360]; +double co[360]; + +int level=1; +int score=0; +int no_levels=0; +int lives=3; +int quit=False; +int dead=False; +Level lev; +int fr_flag; +int title_fr; +#define AT(a,b) *((lev.data)+(a)+((lev.w)*(b))) + + +/* Curses/X mode function calls */ +int (*TitlePage)()=NULL; +int (*Cls)()=NULL; /* Cls(int colour) */ +int (*Put)()=NULL; /* Put(int x,y,SprNum) */ +int (*Centre)()=NULL; /* Centre(char *str;int y,col) */ +int (*Update)()=NULL; +int (*Repaint)()=NULL; /* Repaint (int full_flag) */ +int (*Printf)()=NULL; /* Printf(x,y,col,fmt,....) */ +int (*IntroLevel)()=NULL; +int (*PlayLevel)()=NULL; +int (*LevelWon)()=NULL; +int (*LevelLost)()=NULL; +int (*GameWon)()=NULL; +int (*GameLost)()=NULL; +int (*Show)()=NULL; /* Show(int (*func)(),sleep_fl,quit_fl) */ +int (*EndWindowing)()=NULL; + +/* X Versions */ +int XTitle(); +/* int XCls(); */ +int PutX(); +int XCentre(); +int XUpdate(); +int XRepaint(); +/* int Xprintf(); */ +int XIntroLevel(); +int XPlayLevel(); +int LevelOk(); +int LevelNotOk(); +int XGameOverWon(); +int XGameOverLost(); +int DoTillPress(); +int XEndWindowing(); + +/* Curses Versions */ +int CursesTitle(); +int CursesCls(); +int CursesPut(); +int CursesCentre(); +int CursesRedraw(); +int CursesRepaint(); +int CursesPrintf(int x, int y, int c, const char *fmt, ...); +int CursesIntroLevel(); +int CursesPlayLevel(); +/* int LevelOk(); */ +/* int LevelNotOk(); */ +int CursesGameOverWon(); +int CursesGameOverLost(); +int CursesDoTillPress(); +int CursesEndWindowing(); + + +int main(argc,argv) +int argc; +char *argv[]; + +{ + int f; + XEvent event; + unsigned long evmask; + void IntrHandler(); + + umask(000); + signal(SIGINT,IntrHandler); + + for(f=0;f<360;f++) + { + co[f]=cos((M_PI/180.0)*f); + si[f]=sin((M_PI/180.0)*f); + } + + f=1; + while(f<argc) + { + if(!strcmp(argv[f],"-s")) + { + chsz=8; + f++; + } + else if (!strcmp(argv[f],"-d")) + { + slp=atoi(argv[f+1]); + f+=2; + } + else if (!strcmp(argv[f],"-l")) + { + startlev=atoi(argv[f+1]); + f+=2; + } + else if (!strcmp(argv[f],"-b")) + { + bw=True; + f++; + } + else if (!strcmp(argv[f],"-c")) + { + cursesmode=True; + f++; + } + else if (!strcmp(argv[f],"-h")) + { + LoadScores(); + printf("%3s %7s %-*s %3s\n", + "Pos","Score",HINAMELEN,"Name","Level"); + + for(f=0;f<MAX_HISCORE;f++) + printf("%3d %7d %-*s %3d\n", + f+1,hisc[f].score,HINAMELEN,hisc[f].name,hisc[f].level); + Exit(0); + } + else + { + fprintf(stderr,"%s: usage %s [switches]\n",argv[0],argv[0]); + fprintf(stderr,"-s Use small version\n"); + fprintf(stderr,"-b Use black and white sprites\n"); + fprintf(stderr,"-d delay usleep() by delay for fast servers\n"); + fprintf(stderr,"-l lev start from level lev\n"); + fprintf(stderr,"-c use curses on tty (not yet perfect)\n"); + fprintf(stderr,"-h Dump hi-score table\n"); + Exit(1); + } + } + + srand(getpid()); + + if (!cursesmode) + { + TitlePage=XTitle; + Cls=XCls; + Put=PutX; + Centre=XCentre; + Update=XUpdate; + Repaint=XRepaint; + Printf=Xprintf; + IntroLevel=XIntroLevel; + PlayLevel=XPlayLevel; + LevelWon=LevelOk; + LevelLost=LevelNotOk; + GameWon=XGameOverWon; + GameLost=XGameOverLost; + Show=DoTillPress; + EndWindowing=XEndWindowing; + + size_hints.flags=PPosition|PSize|PMinSize|PMaxSize; + size_hints.x=WINX; + size_hints.y=WINY; + size_hints.width=size_hints.min_width=X(SCRX); + size_hints.height=size_hints.min_height=Y(SCRY); + size_hints.max_width=X(SCRX); + size_hints.max_height=Y(SCRY); + + evmask=ButtonPressMask|KeyPressMask|KeyReleaseMask; + + window=OpenWin(argc,argv,argv[0], + WINX,WINY,X(SCRX),Y(SCRY), + 0,0, + evmask, + &size_hints,&black,&white); + + DisableDoubleBuffer(); + + disp=GetDisplay(); + + if (chsz==16) + font=XUseFont("8x13bold" /*"fixed-screen-b-14"*/); + else + font=XUseFont("5x8"); + + if (bw) + LoadSpritesBW(); + else + LoadSprites(); + } + else + { + chsz=1; + initscr(); + + if ((LINES<SCRY)||(COLS<SCRX)) + { + endwin(); + fprintf(stderr,"%s: expect at least a %dx%d terminal...\n", + argv[0],SCRX,SCRY); + Exit(1); + } + + cbreak(); + noecho(); + nonl(); + nodelay(stdscr,TRUE); + intrflush(stdscr, FALSE); + keypad(stdscr, TRUE); + clear(); + + TitlePage=XTitle; + Cls=CursesCls; + Put=CursesPut; + Centre=CursesCentre; + Update=CursesRedraw; + Repaint=CursesRepaint; + Printf=CursesPrintf; + IntroLevel=CursesIntroLevel; + PlayLevel=CursesPlayLevel; + LevelWon=LevelOk; + LevelLost=LevelNotOk; + GameWon=CursesGameOverWon; + GameLost=CursesGameOverLost; + Show=CursesDoTillPress; + EndWindowing=CursesEndWindowing; + } + + LoadLevelNo(); + + lev.name=lev.data=NULL; + + AutoOff(); + + (*Cls)(black); + title_fr=True; + (*Show)(TitlePage,False,True); + + while(!quit) + { + level=startlev; + lives=3; + score=0; + dead=False; + + do + { + LoadLevel(level); + (*Show)(IntroLevel,False,False); + + fr_flag=True; /* Wish I had client data in my XFunc stuff... */ + + if ((*PlayLevel)()) + { + if (lev.time>0) + while(lev.time) + { + lev.time--; + score+=5; + DrawScore(); + (*Update)(); + } + + for(f=0;f<level*1000;f+=100) + { + score+=100; + DrawScore(); + (*Update)(); + } + + level++; + (*Show)(LevelOk,True,False); + } + else + { + lives--; + if (lives>-1) + (*Show)(LevelNotOk,True,False); + } + } while ((lives>-1)&&(level<=no_levels)); + + (*Cls)(black); + + if (lives==-1) + (*GameLost)(); + else + (*GameWon)(); + + if(score>hisc[MAX_HISCORE-1].score) + EnterHiscore(); + + (*Cls)(black); + title_fr=True; + (*Show)(TitlePage,False,True); + } + + AutoOn(); + + (*EndWindowing)(); +} + + +void IntrHandler() +{ + if (EndWindowing) + (*EndWindowing)(); + + AutoOn(); + + exit(0); +} + +/* --------------------------------------------------------------------- */ + + +AutoOff() + +{ + if (!cursesmode) + { + XAutoRepeatOff(disp); + (*Update)(); + } +} + + +AutoOn() + +{ + if (!cursesmode) + { + XAutoRepeatOn(disp); + (*Update)(); + } +} + + +/* --------------------------------------------------------------------- */ + +char *GetPath() +{ + static char *env=NULL; + char *p; + + if (!env) + { + if (p=getenv("DASHPATH")) + { + env=malloc(strlen(p)+5); + + strcpy(env,p); + + if (env[strlen(env)-1]!='/') + strcat(env,"/"); + } + else + env=strdup("./"); + } + + return(env); +} + + +char *GetFXPath(s) +char *s; + +{ + static char r[256]; + char *p; + + strcpy(r,GetPath()); + + if (bw) + { + if (chsz==16) + strcat(r,"GFX16/"); + else + strcat(r,"GFX8/"); + } + else + { + if (chsz==16) + strcat(r,"GFX16COL/"); + else + strcat(r,"GFX8COL/"); + } + + strcat(r,s); + + return(r); +} + + +char *GetLevelPath(s) +char *s; + +{ + static char r[256]; + char *p; + + strcpy(r,GetPath()); + + if (cursesmode) + strcat(r,"CLEVELS/"); + else + strcat(r,"XLEVELS/"); + + strcat(r,s); + + return(r); +} + + +char *GetLibPath(s) +char *s; + +{ + static char r[256]; + char *p; + + strcpy(r,GetPath()); + + strcat(r,"lib/"); + + strcat(r,s); + + return(r); +} + + +LoadScores() + +{ + int fd,f; + + if ((fd=open(GetLibPath("score"),O_RDONLY))==-1) + return; + + for(f=0;f<MAX_HISCORE;f++) + read(fd,&hisc[f],sizeof(hiscore)); + + close(fd); +} + + +SaveScores() + +{ + int fd,f; + + if ((fd=open(GetLibPath("score"),O_CREAT|O_WRONLY|O_TRUNC,0666))==-1) + return; + + for(f=0;f<MAX_HISCORE;f++) + write(fd,&hisc[f],sizeof(hiscore)); + + close(fd); +} + + +LoadSpritesBW() + +{ + int f,w,h,x,y; + + for(f=0;f<NOSPR;f++) + spr[f].p=GetBitmap(GetFXPath(spr[f].name),&w,&h,&x,&y); +} + + +LoadSprites() + +{ + XColor xc[256]; + XSprite s; + int f,w,h,x,y; + + LoadColormap(GetFXPath("colormap"),xc); + + /* + cm=XCreateColormap(disp,window,DefaultVisual(disp,0),AllocAll); + XSetWindowColormap(disp,window,cm); + XStoreColors(disp,cm,xc,256); + */ + + for(f=0;f<NOSPR;f++) + { + LoadSprite(GetFXPath(spr[f].name),&s,xc); + spr[f].p=s.data; + } +} + + +LoadLevelNo() + +{ + FILE *fp; + + if (!(fp=fopen(GetLevelPath("NO"),"r"))) + { + fprintf(stderr,"Couldn't read %s\n",GetLevelPath("NO")); + Exit(1); + } + + fscanf(fp,"%d",&no_levels); + + fclose(fp); +} + + +LoadLevel(l) +int l; + +{ + char s[256]; + FILE *fp; + int x,y,f,tg; + long oldpos; + + sprintf(s,"%d",l); + + if (!(fp=fopen(GetLevelPath(s),"r"))) + { + fprintf(stderr,"Couldn't read LEVELS/%d\n",l); + AutoOn(); + Exit(1); + } + + if (lev.name) + { + free(lev.name); + free(lev.data); + } + + no_enemy=0; + for(f=0;f<MAX_ENEMY;f++) + enemy[f].alive=False; + + no_generator=0; + + amoeba.alive=False; + + fgets(s,256,fp); + + s[strlen(s)-1]=NULL; + lev.name=strdup(s); + + fgets(s,256,fp); + sscanf(s,"%d,%d",&lev.x,&lev.y); + + fgets(s,256,fp); + sscanf(s,"%d",&lev.toget); + lev.no=0; + + if (!lev.toget) + tg=True; + else + tg=False; + + fgets(s,256,fp); + sscanf(s,"%d",&lev.time); + + fgets(s,256,fp); + sscanf(s,"%d,%d",&max_amoeba_size,&amoeba_move_chance); + + x=y=0; + lev.sx=lev.sy=-1; + lev.ex=lev.ey=-1; + + oldpos=ftell(fp); + + fgets(s,256,fp); + lev.w=strlen(s)-1; + + lev.h=0; + fgets(s,256,fp); + while(!feof(fp)) + { + lev.h++; + fgets(s,256,fp); + } + + clearerr(fp); + fseek(fp,oldpos,0); + + lev.data=(char *)malloc(lev.w*lev.h); + + fgets(s,256,fp); + + for(y=0;y<lev.h;y++) + { + s[strlen(s)-1]=NULL; + if (strlen(s)!=lev.w) + { + fprintf(stderr,"Corrupt level file!\n"); + AutoOn(); + Exit(1); + } + + if (feof(fp)) + { + fprintf(stderr,"Corrupt level file!\n"); + AutoOn(); + Exit(1); + } + + x=0; + for(f=0;f<strlen(s);f++,x++) + switch (s[f]) + { + case SPACEGLY: + AT(x,y)=SPACESPR; + break; + case EARTHGLY: + AT(x,y)=EARTHSPR; + break; + case ROCKGLY: + AT(x,y)=ROCKSPR; + break; + case TUFFWALLGLY: + AT(x,y)=TUFFWALLSPR; + break; + case WALLGLY: + AT(x,y)=WALLSPR; + break; + case GEMGLY: + AT(x,y)=GEMSPR; + if (tg) + lev.toget++; + break; + case HEROGLY: + AT(x,y)=EARTHSPR; + lev.sx=x; + lev.sy=y; + break; + case EXITGLY: + AT(x,y)=EXITSPR; + lev.ex=x; + lev.ey=y; + break; + case BUTTGLY: + AT(x,y)=BUTTSPR; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=BUTTSPR; + enemy[no_enemy].x=x; + enemy[no_enemy].y=y; + enemy[no_enemy].dir=UP; + enemy[no_enemy].moved=False; + if ((++no_enemy)>MAX_ENEMY) + { + fprintf(stderr,"Error! To many enemies level file!\n"); + AutoOn(); + Exit(1); + } + break; + case CHSRGLY: + AT(x,y)=CHSRSPR; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=CHSRSPR; + enemy[no_enemy].x=x; + enemy[no_enemy].y=y; + enemy[no_enemy].dir=UP; + enemy[no_enemy].moved=False; + if ((++no_enemy)>MAX_ENEMY) + { + fprintf(stderr,"Error! To many enemies level file!\n"); + AutoOn(); + Exit(1); + } + break; + case ROCKSWGLY: + AT(x,y)=ROCKSWSPR; + break; + case ONEUPGLY: + AT(x,y)=ONEUPSPR; + break; + case FILTERGLY: + AT(x,y)=FILTERSPR; + break; + case AMOEBAGLY: + AT(x,y)=AMOEBASPR; + if (amoeba.alive) + { + amoeba.size++; + } + else + { + amoeba.alive=True; + amoeba.size=1; + amoeba.count=AMOEBA_COUNT; + amoeba.could_move=False; + } + break; + case ROCKGENGLY: + AT(x,y)=ROCKGENSPR; + generator[no_generator].cycle=0; + generator[no_generator].type=ROCKGENSPR; + generator[no_generator].x=x; + generator[no_generator].y=y; + if ((++no_generator)>MAX_GENERATOR) + { + fprintf(stderr,"Error! To many generators!\n"); + AutoOn(); + Exit(1); + } + break; + case BUTTGENGLY: + AT(x,y)=BUTTGENSPR; + generator[no_generator].cycle=0; + generator[no_generator].type=BUTTGENSPR; + generator[no_generator].x=x; + generator[no_generator].y=y; + if ((++no_generator)>MAX_GENERATOR) + { + fprintf(stderr,"Error! To many generators!\n"); + AutoOn(); + Exit(1); + } + break; + case CHSRGENGLY: + AT(x,y)=CHSRGENSPR; + generator[no_generator].cycle=0; + generator[no_generator].type=CHSRGENSPR; + generator[no_generator].x=x; + generator[no_generator].y=y; + if ((++no_generator)>MAX_GENERATOR) + { + fprintf(stderr,"Error! To many generators!\n"); + AutoOn(); + Exit(1); + } + break; + default: + break; + } + + fgets(s,256,fp); + } + + if ((lev.sx==-1)) + { + fprintf(stderr,"Error! No miner in level file!\n"); + AutoOn(); + Exit(1); + } + + if ((lev.ex==-1)) + { + fprintf(stderr,"Error! No exit in level file!\n"); + AutoOn(); + Exit(1); + } +} + +PutX(x,y,n) + +{ + XPut(spr[n].p,0,0,chsz,chsz,X(x),Y(y)); +} + +XCentre(s,y,c) +char *s; +int y,c; + +{ + XPrint(X(SCRX)/2-strlen(s)*((font->max_bounds.width)>>1),y,s,c); +} + + +CursesCentre(s,y,c) +char *s; +int y,c; + +{ + /* mvaddstr(y,SCRX/2-strlen(s)/2,s); */ + mvaddstr(y,COLS/2-strlen(s)/2,s); +} + + +DoTillPress(f,s,qf) +int (*f)(); +int s,qf; + +{ + XEvent e; + + if(XPending(disp)) + XNextEvent(disp,&e); + + while(1) + { + if ((slp>-1)&&(s)) + USLEEP(slp); + + if(XPending(disp)) + { + XNextEvent(disp,&e); + + switch(e.type) + { + case KeyPress: + switch(XLookupKeysym((XKeyEvent *)&e,ShiftMapIndex)) + { + case XK_space: + return; + break; + + case XK_Escape: + if (qf) + { + quit=True; + return; + } + break; + + default: + break; + } + break; + + case ButtonPress: + return; + break; + default: + break; + } + } + + (*f)(); + } +} + +/* --------------------------------------------------------------------- */ + +#define TITLEBLKS 44 +#define TBX(x1,x2) (14+(x1*4)+x2) +#define TBY(y) (5+(y)) + +static struct + { + int x,y; + } title_bl[TITLEBLKS]= + { + {TBX(0,0), TBY(4)}, /* D */ + {TBX(0,1), TBY(4)}, /* D */ + {TBX(0,0), TBY(3)}, /* D */ + {TBX(0,2), TBY(3)}, /* D */ + {TBX(0,0), TBY(2)}, /* D */ + {TBX(0,2), TBY(2)}, /* D */ + {TBX(0,0), TBY(1)}, /* D */ + {TBX(0,2), TBY(1)}, /* D */ + {TBX(0,0), TBY(0)}, /* D */ + {TBX(0,1), TBY(0)}, /* D */ + + {TBX(1,0), TBY(4)}, /* A */ + {TBX(1,2), TBY(4)}, /* A */ + {TBX(1,0), TBY(3)}, /* A */ + {TBX(1,2), TBY(3)}, /* A */ + {TBX(1,0), TBY(2)}, /* A */ + {TBX(1,1), TBY(2)}, /* A */ + {TBX(1,2), TBY(2)}, /* A */ + {TBX(1,0), TBY(1)}, /* A */ + {TBX(1,2), TBY(1)}, /* A */ + {TBX(1,0), TBY(0)}, /* A */ + {TBX(1,1), TBY(0)}, /* A */ + {TBX(1,2), TBY(0)}, /* A */ + + {TBX(2,0), TBY(4)}, /* S */ + {TBX(2,1), TBY(4)}, /* S */ + {TBX(2,2), TBY(4)}, /* S */ + {TBX(2,2), TBY(3)}, /* S */ + {TBX(2,2), TBY(2)}, /* S */ + {TBX(2,1), TBY(2)}, /* S */ + {TBX(2,0), TBY(2)}, /* S */ + {TBX(2,0), TBY(1)}, /* S */ + {TBX(2,0), TBY(0)}, /* S */ + {TBX(2,1), TBY(0)}, /* S */ + {TBX(2,2), TBY(0)}, /* S */ + + {TBX(3,0), TBY(4)}, /* H */ + {TBX(3,2), TBY(4)}, /* H */ + {TBX(3,0), TBY(3)}, /* H */ + {TBX(3,2), TBY(3)}, /* H */ + {TBX(3,0), TBY(2)}, /* H */ + {TBX(3,1), TBY(2)}, /* H */ + {TBX(3,2), TBY(2)}, /* H */ + {TBX(3,0), TBY(1)}, /* H */ + {TBX(3,2), TBY(1)}, /* H */ + {TBX(3,0), TBY(0)}, /* H */ + {TBX(3,2), TBY(0)} /* H */ + }; + + +int XTitle() + +{ + static int fr=True; + static int bln=0; + static int x=0; + static int y=0; + static int sc=0; + static int sct=0; + char s[128]; + int f; + + if (title_fr) + { + x=title_bl[0].x; + y=0; + title_fr=False; + LoadScores(); + + sc=0; + bln=0; + sct=0; + + (*Centre)("ALL TIME DASHERS",Y(12),white); + + if (!cursesmode) + { + (*Printf)(0,Y(13),white,"%3s %7s %-*s %3s", + "Pos","Score",HINAMELEN,"Name","Level"); + + (*Centre)("Press Escape to quit",Y(SCRY-4),white); + } + else + (*Centre)("^C to quit",Y(SCRY-4),white); + + (*Centre)("Press Space to continue",Y(SCRY-2),white); + } + + if (!cursesmode) + { + XFillBox(0,Y(14),X(SCRX),Y(3),black); + + (*Printf)(0,Y(15),white,"%3d %7d %-*s %3d", + sc+1,hisc[sc].score,HINAMELEN,hisc[sc].name,hisc[sc].level); + } + else + { + (*Printf)(0,Y(15),white,"Pos : %-2d",sc+1); + (*Printf)(0,Y(16),white,"Name : %-*s",HINAMELEN,hisc[sc].name); + (*Printf)(0,Y(17),white,"Score : %-7d",hisc[sc].score); + (*Printf)(0,Y(18),white,"Level : %-3d",hisc[sc].level); + } + + if (sct++==100) + { + sct=0; + if (++sc==MAX_HISCORE) + sc=0; + } + + if (y>=title_bl[bln].y) + if (++bln<TITLEBLKS) + { + x=title_bl[bln].x; + y=0; + } + + if (bln<TITLEBLKS) + { + if (y) + (*Put)(x,y-1,SPACESPR); + + (*Put)(x,y++,GEMSPR); + } + + (*Update)(); + + return(XFUNCCONT); +} + +/* --------------------------------------------------------------------- */ + +#define INTROSPR 30 + +struct + { + int x,y; + } ispr[INTROSPR]; + +XIntroLevel() + +{ + static int fr=True; + char s[100]; + int f; + + if (fr) + { + for(f=0;f<INTROSPR;f++) + { + ispr[f].x=X(RND(SCRX)); + ispr[f].y=Y(RND(SCRY)); + } + + fr=False; + } + + (*Cls)(black); + + for(f=0;f<INTROSPR;f++) + { + XPut(spr[GEMSPR].p,0,0,chsz,chsz,ispr[f].x,ispr[f].y); + + if ((ispr[f].y+=2)>Y(SCRY)) + { + ispr[f].x=X(RND(SCRX)); + ispr[f].y=-chsz; + } + } + + sprintf(s,"Level %d",level); + (*Centre)(s,Y(3),white); + + sprintf(s,"'%s'",lev.name); + (*Centre)(s,Y(5),white); + + (*Centre)("Press Space to continue",Y(SCRY-2),white); + + (*Update)(); + + return(XFUNCCONT); +} + +/* --------------------------------------------------------------------- */ + +int LevelOk() + +{ + static int ix=1; + int x,y; + + if (fr_flag) + { + fr_flag=False; + + LoadLevel(WELLDONELEV); + + ix=1; + + (*Cls)(black); + (*Repaint)(True); + } + else + (*Repaint)(False); + + lev.x+=ix; + + if ((lev.x==0)||(lev.x==lev.w-SCRX)) + { + ix=-ix; + + for(x=0;x<lev.w;x++) + for(y=0;y<lev.h;y++) + if (AT(x,y)==EARTHSPR) + AT(x,y)=SPACESPR; + } + + DrawMess("Press Space"); + + (*Update)(); + + Gravity(); +} + + +int LevelNotOk() + +{ + static int ix=1; + int x,y; + + if (fr_flag) + { + fr_flag=False; + + ix=1; + + LoadLevel(TRYAGAINLEV); + + (*Repaint)(True); + } + else + (*Repaint)(False); + + lev.x+=ix; + + if ((lev.x==0)||(lev.x==lev.w-SCRX)) + { + ix=-ix; + + for(x=0;x<lev.w;x++) + for(y=0;y<lev.h;y++) + if (AT(x,y)==EARTHSPR) + AT(x,y)=SPACESPR; + } + + DrawMess("Press Space"); + + (*Update)(); + + Gravity(); +} + +/* --------------------------------------------------------------------- */ + +DrawMess(s) +char *s; + +{ + if (!cursesmode) + XFillBox(0,0,X(SCRX),Y(1)-1,black); + + (*Centre)(s,((cursesmode) ? (0) : (Y(1)-2)),white); +} + + +DrawScore() + +{ + if (!cursesmode) + { + XFillBox(0,0,X(SCRX),Y(1)-1,black); + + (*Printf)(0,(Y(1)-2),white, + "Score %7d Collect %3d Got %3d Lives %2d Time %4d", + score,lev.toget,lev.no,lives,lev.time); + } + else + if (COLS>=80) + (*Printf)(0,0,white, + "Score %7d Collect %3d Got %3d Lives %2d Time %4d", + score,lev.toget,lev.no,lives,lev.time); + else + (*Printf)(0,0,white,"S:%-7d C:%-3d G:%-3d L:%-2d T:%-4d", + score,lev.toget,lev.no,lives,lev.time); +} + + +XUpdate() + +{ + Redraw(0,0); +} + + +XRepaint(full) + +{ + static char scr[SCRX][SCRY]; + static int lx,ly; + int x,y,px,py; + + if (full) + { + lx=lev.x; + ly=lev.y; + + for(y=0;y<SCRY;y++) + for(x=0;x<SCRX;x++) + scr[x][y]=VOIDSPR; + } + else + { + px=lx-lev.x; + py=ly-lev.y; + + if (px==-1) + { + XCopy(X(1),Y(1),X(SCRX-1),Y(SCRY-1),X(0),Y(1)); + for (x=1;x<SCRX;x++) + for(y=0;y<SCRY;y++) + scr[x-1][y]=scr[x][y]; + + for(y=0;y<SCRY;y++) + scr[SCRX-1][y]=VOIDSPR; + } + + if (px==1) + { + XCopy(X(0),Y(1),X(SCRX-1),Y(SCRY-1),X(1),Y(1)); + for (x=SCRX-1;x>0;x--) + for(y=0;y<SCRY;y++) + scr[x][y]=scr[x-1][y]; + + for(y=0;y<SCRY;y++) + scr[0][y]=VOIDSPR; + } + + if (py==-1) + { + XCopy(X(0),Y(2),X(SCRX),Y(SCRY-2),X(0),Y(1)); + for (x=0;x<SCRX;x++) + for(y=1;y<SCRY;y++) + scr[x][y-1]=scr[x][y]; + + for(x=0;x<SCRX;x++) + scr[x][SCRY-1]=VOIDSPR; + } + + if (py==1) + { + XCopy(X(0),Y(1),X(SCRX),Y(SCRY-2),X(0),Y(2)); + for (x=0;x<SCRX;x++) + for(y=SCRY-1;y>0;y--) + scr[x][y]=scr[x][y-1]; + + for(x=0;x<SCRX;x++) + scr[x][1]=VOIDSPR; + } + } + + for(y=1;y<SCRY;y++) + for(x=0;x<SCRX;x++) + { + px=lev.x+x; + py=lev.y+y-1; + + if ((px<lev.w)&&(py<lev.h)&&(px>-1)&&(py>-1)) + { + if (scr[x][y]!=AT(px,py)) + { + (*Put)(x,y,AT(px,py)); + scr[x][y]=AT(px,py); + } + } + else + if (scr[x][y]!=SPACESPR) + { + (*Put)(x,y,SPACESPR); + scr[x][y]=SPACESPR; + } + } + + lx=lev.x; + ly=lev.y; +} + +/* --------------------------------------------------------------------- */ +#define MOVE_AMOEBA(x,y) ((AT(x,y)==SPACESPR)||(AT(x,y)==EARTHSPR)) + +CheckAmoebaMove(x,y) + +{ + int r=False; + + if (MOVE_AMOEBA(x-1,y)) + { + r=True; + if (RND(100)>amoeba_move_chance) + { + AT(x-1,y)=AMOEBASPR; + amoeba.size++; + } + } + + if (MOVE_AMOEBA(x+1,y)) + { + r=True; + if (RND(100)>amoeba_move_chance) + { + AT(x+1,y)=AMOEBASPR; + amoeba.size++; + } + } + + if (MOVE_AMOEBA(x,y-1)) + { + r=True; + if (RND(100)>amoeba_move_chance) + { + AT(x,y-1)=AMOEBASPR; + amoeba.size++; + } + } + + if (MOVE_AMOEBA(x,y+1)) + { + r=True; + if (RND(100)>amoeba_move_chance) + { + AT(x,y+1)=AMOEBASPR; + amoeba.size++; + } + } + + return(r); +} + +HandleAmoeba() + +{ + int f,x,y,d; + + if (amoeba.alive) + if (!(--amoeba.count)) + { + amoeba.count=AMOEBA_COUNT; + amoeba.could_move=False; + + for(y=0;y<lev.h;y++) + for(x=0;x<lev.w;x++) + if (AT(x,y)==AMOEBASPR) + if (CheckAmoebaMove(x,y)) + amoeba.could_move=True; + + if (amoeba.size>max_amoeba_size) + { + for(y=0;y<lev.h;y++) + for(x=0;x<lev.w;x++) + if (AT(x,y)==AMOEBASPR) + AT(x,y)=ROCKSPR; + } + else + if (!amoeba.could_move) + { + for(y=0;y<lev.h;y++) + for(x=0;x<lev.w;x++) + if (AT(x,y)==AMOEBASPR) + AT(x,y)=GEMSPR; + } + } +} + + +/* --------------------------------------------------------------------- */ + +GenerateMonsters(x,y,t) +int x,y,t; + +{ + if ((AT(x-1,y)==SPACESPR)&&(no_enemy<MAX_ENEMY)) + { + AT(x-1,y)=t; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=t; + enemy[no_enemy].x=x-1; + enemy[no_enemy].y=y; + enemy[no_enemy].dir=LEFT; + enemy[no_enemy].moved=False; + no_enemy++; + } + + if ((AT(x+1,y)==SPACESPR)&&(no_enemy<MAX_ENEMY)) + { + AT(x+1,y)=t; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=t; + enemy[no_enemy].x=x+1; + enemy[no_enemy].y=y; + enemy[no_enemy].dir=RIGHT; + enemy[no_enemy].moved=False; + no_enemy++; + } + + if ((AT(x,y+1)==SPACESPR)&&(no_enemy<MAX_ENEMY)) + { + AT(x,y+1)=t; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=t; + enemy[no_enemy].x=x; + enemy[no_enemy].y=y+1; + enemy[no_enemy].dir=DOWN; + enemy[no_enemy].moved=False; + no_enemy++; + } + + if ((AT(x,y-1)==SPACESPR)&&(no_enemy<MAX_ENEMY)) + { + AT(x,y-1)=t; + enemy[no_enemy].alive=True; + enemy[no_enemy].type=t; + enemy[no_enemy].x=x; + enemy[no_enemy].y=y-1; + enemy[no_enemy].dir=UP; + enemy[no_enemy].moved=False; + no_enemy++; + } +} + + +HandleGenerators() + +{ + Generator *g; + int f; + + for(f=0;f<no_generator;f++) + { + g=&generator[f]; + + AT(g->x,g->y)=g->type; /* Make generators 'indestructible' */ + + if (!((g->cycle++)%20)) + switch(g->type) + { + case ROCKGENSPR: + if (AT(g->x,g->y+1)==SPACESPR) + AT(g->x,g->y+1)=ROCKFALLSPR; + break; + + case BUTTGENSPR: + GenerateMonsters(g->x,g->y,BUTTSPR); + break; + + case CHSRGENSPR: + GenerateMonsters(g->x,g->y,CHSRSPR); + break; + + default: + break; + } + } +} + + +/* --------------------------------------------------------------------- */ + +CheckEnemyMove(e,d) +Enemy *e; +int d; + +{ + switch(AT((e)->x+move_tbl[(d)].x,(e)->y+move_tbl[(d)].y)) + { + case SPACESPR: + case HEROSPR: + return(True); + break; + default: + return(False); + break; + } +} + +#define ISDESTRUCT(c) \ + ((c==SPACESPR)|| \ + (c==EARTHSPR)|| \ + (c==ROCKSPR)|| \ + (c==WALLSPR)|| \ + (c==GEMSPR)|| \ + (c==HEROSPR)|| \ + (c==ROCKFALLSPR)|| \ + (c==GEMFALLSPR)|| \ + (c==BUTTSPR)|| \ + (c==CHSRSPR)) + +HandleEnemies() + +{ + int f; + + for(f=0;f<no_enemy;f++) + if (enemy[f].alive) + switch(enemy[f].type) + { + case BUTTSPR: + HandleButt(&enemy[f]); + break; + + case CHSRSPR: + HandleChsr_V2(&enemy[f]); + break; + + default: + break; + } +} + + +HandleButt(e) +Enemy *e; + +{ + int x,y,b; + + switch (AT(e->x,e->y)) + { + case ROCKFALLSPR: + case GEMFALLSPR: + e->alive=False; + score+=20; + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (ISDESTRUCT(AT(e->x+x,e->y+y))) + AT(e->x+x,e->y+y)=GEMFALLSPR; + return; + break; + + default: + AT(e->x,e->y)=SPACESPR; + + if (CheckEnemyMove(e,e->dir)) + { + e->x+=move_tbl[e->dir].x; + e->y+=move_tbl[e->dir].y; + } + else + { + if (CheckEnemyMove(e,ROT_RIGHT(e->dir))) + e->dir=ROT_RIGHT(e->dir); + else + e->dir=ROT_LEFT(e->dir); + } + AT(e->x,e->y)=BUTTSPR; + } +} + + +HandleChsr(e) +Enemy *e; + +{ + int x,y,f,od,md; + + switch (AT(e->x,e->y)) + { + case ROCKFALLSPR: + case GEMFALLSPR: + e->alive=False; + score+=20; + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (ISDESTRUCT(AT(e->x+x,e->y+y))) + AT(e->x+x,e->y+y)=ROCKFALLSPR; + return; + break; + + default: + AT(e->x,e->y)=SPACESPR; + + if ((od=e->dir)==NONE) + { + od=UP; + e->moved=False; + } + + if (e->dir!=NONE) + if(!CheckEnemyMove(e,e->dir)) + { + e->dir=NONE; + e->moved=False; + } + + if(e->moved) + { + md=e->dir; + e->dir=NONE; + } + else + md=NONE; + + /* Try moving in the X plane towards the sprite */ + if (e->dir==NONE) + { + x=lev.sx-e->x; + + if (x<0) + e->dir=LEFT; + else + e->dir=RIGHT; + + if (e->dir!=NONE) + if(!CheckEnemyMove(e,e->dir)) + e->dir=NONE; + } + + if (md!=NONE) + if (md==ROT_FLIP(e->dir)) + e->dir=NONE; + + /* Try moving in the Y plane towards the sprite */ + if (e->dir==NONE) + { + y=lev.sy-e->y; + + if (y<0) + e->dir=UP; + else + e->dir=LEFT; + + if (e->dir!=NONE) + if(!CheckEnemyMove(e,e->dir)) + e->dir=NONE; + } + + if (md!=NONE) + if (md==ROT_FLIP(e->dir)) + { + e->dir=md; + e->moved=True; + } + + /* Try any other direction */ + if (e->dir==NONE) + { + if (CheckEnemyMove(e,ROT_RIGHT(od))) + { + e->dir=ROT_RIGHT(od); + e->moved=True; + } + + if (e->dir==NONE) + if (CheckEnemyMove(e,ROT_LEFT(od))) + { + e->dir=ROT_LEFT(od); + e->moved=True; + } + + if (e->dir==NONE) + if (CheckEnemyMove(e,ROT_FLIP(od))) + { + e->dir=ROT_LEFT(od); + e->moved=True; + } + } + + if (e->dir!=NONE) + { + e->x+=move_tbl[e->dir].x; + e->y+=move_tbl[e->dir].y; + } + + AT(e->x,e->y)=CHSRSPR; + break; + } +} + + +HandleChsr_V2(e) +Enemy *e; + +{ + int x,y,b; + + switch (AT(e->x,e->y)) + { + case ROCKFALLSPR: + case GEMFALLSPR: + e->alive=False; + score+=20; + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (AT(e->x+x,e->y+y)!=TUFFWALLSPR) + AT(e->x+x,e->y+y)=ROCKFALLSPR; + return; + break; + + default: + + if (e->moved) + { + e->moved--; + return; + } + + e->moved=3; + + AT(e->x,e->y)=SPACESPR; + + e->dir=NONE; + + if (lev.sy<e->y) + e->dir=UP; + else + if (lev.sy>e->y) + e->dir=DOWN; + + if (e->dir!=NONE) + { + b=AT(e->x+move_tbl[e->dir].x,e->y+move_tbl[e->dir].y); + + if ((b!=SPACESPR)&&(b!=HEROSPR)) + e->dir=NONE; + } + + if (e->dir==NONE) + { + if (lev.sx<e->x) + e->dir=LEFT; + else + if (lev.sx>e->x) + e->dir=RIGHT; + + if (e->dir!=NONE) + { + b=AT(e->x+move_tbl[e->dir].x,e->y+move_tbl[e->dir].y); + + if ((b!=SPACESPR)&&(b!=HEROSPR)) + e->dir=NONE; + } + } + + if (e->dir!=NONE) + { + e->x+=move_tbl[e->dir].x; + e->y+=move_tbl[e->dir].y; + } + + AT(e->x,e->y)=CHSRSPR; + } +} + + +HandleChsr_V1(e) +Enemy *e; + +{ + switch (AT(e->x,e->y)) + { + case ROCKFALLSPR: + case GEMFALLSPR: + e->alive=False; + score+=20; + return; + break; + + default: + AT(e->x,e->y)=SPACESPR; + + e->x+=move_tbl[e->dir].x; + e->y+=move_tbl[e->dir].y; + + if ((AT(e->x,e->y)!=SPACESPR)&&(AT(e->x,e->y)!=HEROSPR)) + { + e->x-=move_tbl[e->dir].x; + e->y-=move_tbl[e->dir].y; + + if ((++e->dir)>LEFT) + e->dir=UP; + } + AT(e->x,e->y)=CHSRSPR; + } +} + + +/* --------------------------------------------------------------------- */ + +CanMove(d) + +{ + if (d==NONE) + return(False); + + switch(AT(lev.sx+move_tbl[d].x,lev.sy+move_tbl[d].y)) + { + case ROCKSPR: + if ((d==LEFT)||(d==RIGHT)) + { + if (AT(lev.sx+move_tbl[d].x*2,lev.sy+move_tbl[d].y*2)==SPACESPR) + { + AT(lev.sx+move_tbl[d].x*2,lev.sy+move_tbl[d].y*2)=ROCKSPR; + AT(lev.sx+move_tbl[d].x,lev.sy+move_tbl[d].y)=SPACESPR; + } + else + return(False); + } + else + return(False); + break; + + case TUFFWALLSPR: + case WALLSPR: + case ROCKFALLSPR: + case GEMFALLSPR: + case AMOEBASPR: + case FILTERSPR: + case ROCKGENSPR: + case BUTTGENSPR: + case CHSRGENSPR: + return(False); + break; + + case EXITSPR: + if (lev.no>=lev.toget) + return(True); + else + return(False); + + + default: + return(True); + break; + } +} + + +CheckEnemies() + +{ + int f,x,y; + + for(f=0;f<no_enemy;f++) + if (enemy[f].alive) + if ((enemy[f].x==lev.sx)&&(enemy[f].y==lev.sy)) + switch(enemy[f].type) + { + case BUTTSPR: + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (AT(lev.sx+x,lev.sy+y)!=TUFFWALLSPR) + AT(lev.sx+x,lev.sy+y)=GEMFALLSPR; + return(False); + break; + + case CHSRSPR: + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (AT(lev.sx+x,lev.sy+y)!=TUFFWALLSPR) + AT(lev.sx+x,lev.sy+y)=ROCKFALLSPR; + return(False); + break; + + default: + break; + } + + return(True); +} + + +Handle(c) +int c; + +{ + int x,y; + + switch(c) + { + case SPACESPR: + break; + + case EARTHSPR: + /* score+=10; */ + break; + + case ROCKSPR: + case ROCKFALLSPR: + case GEMFALLSPR: + for(x=-1;x<2;x++) + for(y=-1;y<2;y++) + if (AT(lev.sx+x,lev.sy+y)!=TUFFWALLSPR) + AT(lev.sx+x,lev.sy+y)=ROCKFALLSPR; + return(False); + break; + + case WALLSPR: + break; + + case GEMSPR: + score+=10; + lev.no++; + break; + + case ROCKSWSPR: + for(x=0;x<lev.w;x++) + for(y=0;y<lev.h;y++) + switch (AT(x,y)) + { + case ROCKSPR: + case ROCKFALLSPR: + AT(x,y)=WALLSPR; + break; + case WALLSPR: + AT(x,y)=ROCKSPR; + default: + break; + } + return(True); + break; + + case ONEUPSPR: + lives++; + break; + + case EXITSPR: + return(False); + break; + + default: + break; + + } + + return(True); +} + + +HandlePush(d,x,y) +int d,x,y; + +{ + int c; + int lx,ly; + + switch(c=AT(x,y)) + { + case SPACESPR: + break; + + case EARTHSPR: + AT(x,y)=SPACESPR; + break; + + case ROCKSPR: + if ((d==LEFT)||(d==RIGHT)) + if (AT(x+move_tbl[d].x,y+move_tbl[d].y)==SPACESPR) + { + AT(x+move_tbl[d].x,y+move_tbl[d].y)=ROCKSPR; + AT(x,y)=SPACESPR; + } + break; + + case ROCKFALLSPR: + case GEMFALLSPR: + break; + + case WALLSPR: + break; + + case GEMSPR: + score+=10; + lev.no++; + AT(x,y)=SPACESPR; + break; + + case ROCKSWSPR: + for(lx=0;lx<lev.w;lx++) + for(ly=0;ly<lev.h;ly++) + switch (AT(lx,ly)) + { + case ROCKSPR: + case ROCKFALLSPR: + AT(lx,ly)=WALLSPR; + break; + case WALLSPR: + AT(lx,ly)=ROCKSPR; + default: + break; + } + AT(x,y)=SPACESPR; + break; + + case ONEUPSPR: + lives++; + AT(x,y)=SPACESPR; + break; + + case EXITSPR: + lev.sx=lev.ex; + lev.sy=lev.ey; + return(False); + break; + + default: + break; + + } + + return(True); +} + + +#define ISSTOP(b) ((b==ROCKSPR)||(b==ROCKFALLSPR)|| \ + (b==WALLSPR)||(b==TUFFWALLSPR)||(b==EARTHSPR)|| \ + (b==GEMSPR)||(b==GEMFALLSPR)||(b==EXITSPR)||\ + (b==AMOEBASPR)||(b==ROCKGENSPR)||(b==BUTTGENSPR)||\ + (b==CHSRGENSPR)) + +Gravity() + +{ + int x,y,b,l,r,l2,r2; + + for(y=lev.h-1;y>-1;y--) + for(x=0;x<lev.w;x++) + switch(AT(x,y)) + { + case ROCKFALLSPR: + l=AT(x-1,y+1); + l2=AT(x-1,y); + r=AT(x+1,y+1); + r2=AT(x+1,y); + b=AT(x,y+1); + + if (ISSTOP(b)) + { + if (ISSTOP(r)&&(!ISSTOP(l))&&(l2==SPACESPR)) + { + AT(x,y)=SPACESPR; + AT(x-1,y+1)=ROCKFALLSPR; + } + else if (ISSTOP(l)&&(!ISSTOP(r))&&(r2==SPACESPR)) + { + AT(x,y)=SPACESPR; + AT(x+1,y+1)=ROCKFALLSPR; + } + else + AT(x,y)=ROCKSPR; + } + else + { + if (b!=FILTERSPR) + { + AT(x,y)=SPACESPR; + AT(x,y+1)=ROCKFALLSPR; + } + else + { + AT(x,y)=SPACESPR; + if (AT(x,y+2)==SPACESPR) + AT(x,y+2)=GEMFALLSPR; + } + } + + break; + + case GEMFALLSPR: + l=AT(x-1,y+1); + l2=AT(x-1,y); + r=AT(x+1,y+1); + r2=AT(x+1,y); + b=AT(x,y+1); + + if (ISSTOP(b)) + { + if (ISSTOP(r)&&(!ISSTOP(l))&&(l2==SPACESPR)) + { + AT(x,y)=SPACESPR; + AT(x-1,y+1)=GEMFALLSPR; + } + else if (ISSTOP(l)&&(!ISSTOP(r))&&(r2==SPACESPR)) + { + AT(x,y)=SPACESPR; + AT(x+1,y+1)=GEMFALLSPR; + } + else + AT(x,y)=GEMSPR; + } + else + { + if (b!=FILTERSPR) + { + AT(x,y)=SPACESPR; + AT(x,y+1)=GEMFALLSPR; + } + else + { + AT(x,y)=SPACESPR; + if (AT(x,y+2)==SPACESPR) + AT(x,y+2)=ROCKFALLSPR; + } + } + + break; + + case ROCKSPR: + l=AT(x-1,y+1); + l2=AT(x-1,y); + r=AT(x+1,y+1); + r2=AT(x+1,y); + b=AT(x,y+1); + + if (b==SPACESPR) + { + AT(x,y)=SPACESPR; + AT(x,y+1)=ROCKFALLSPR; + } + else if ((r==SPACESPR)&&(r2==SPACESPR)&& + ((b==GEMSPR)||(b==ROCKSPR)||(b==WALLSPR)|| + (b==TUFFWALLSPR))) + { + AT(x,y)=SPACESPR; + AT(x+1,y+1)=ROCKFALLSPR; + } + else if ((l==SPACESPR)&&(l2==SPACESPR)&& + ((b==GEMSPR)||(b==ROCKSPR)||(b==WALLSPR)|| + (b==TUFFWALLSPR))) + { + AT(x,y)=SPACESPR; + AT(x-1,y+1)=ROCKFALLSPR; + } + break; + + case GEMSPR: + l=AT(x-1,y+1); + l2=AT(x-1,y); + r=AT(x+1,y+1); + r2=AT(x+1,y); + b=AT(x,y+1); + + if (b==SPACESPR) + { + AT(x,y)=SPACESPR; + AT(x,y+1)=GEMFALLSPR; + } + else if ((r==SPACESPR)&&(r2==SPACESPR)& + ((b==GEMSPR)||(b==ROCKSPR)||(b==WALLSPR)|| + (b==TUFFWALLSPR))) + { + AT(x,y)=SPACESPR; + AT(x+1,y+1)=GEMFALLSPR; + } + else if ((l==SPACESPR)&&(l2==SPACESPR)& + ((b==GEMSPR)||(b==ROCKSPR)||(b==WALLSPR)|| + (b==TUFFWALLSPR))) + { + AT(x,y)=SPACESPR; + AT(x-1,y+1)=GEMFALLSPR; + } + break; + + default: + break; + } +} + + +XPlayLevel() + +{ + XEvent e; + int dir=NONE; + int x,y,ok,ls,kp,kpm,dt,ti; + int f,r; + int shiftmode,shiftrelease; + int pressed[4],released[4]; + + AT(lev.sx,lev.sy)=HEROSPR; + (*Cls)(black); + (*Repaint)(True); + DrawScore(); + (*Update)(); + + ok=True; + dt=20; + ti=0; + + for(f=0;f<4;f++) + { + pressed[f]=0; + released[f]=False; + } + + shiftmode=False; + shiftrelease=False; + + while(dt) + { + if (slp>-1) + USLEEP(slp); + + for(f=0;f<4;f++) + if (released[f]) + { + pressed[f]=0; + released[f]=False; + + if (f==dir) + dir=NONE; + } + + if (dir==NONE) + { + kp=-1; + kpm=0; + + for(f=0;f<4;f++) + if (pressed[f]>kpm) + { + kpm=pressed[f]; + kp=f; + } + + if (kp!=-1) + dir=kp; + } + + if (shiftrelease) + { + shiftmode=False; + shiftrelease=False; + } + + while(XPending(disp)) + { + XNextEvent(disp,&e); + + switch(e.type) + { + case KeyPress: + switch(XLookupKeysym((XKeyEvent *)&e,ShiftMapIndex)) + { + case XK_Shift_L: + case XK_Shift_R: + shiftmode=True; + break; + + case XK_Up: + for(f=0;f<4;f++) + if (pressed[f]>0) + pressed[f]++; + + pressed[UP]=1; + dir=UP; + break; + + case XK_Left: + for(f=0;f<4;f++) + if (pressed[f]>0) + pressed[f]++; + + pressed[LEFT]=1; + dir=LEFT; + break; + + case XK_Down: + for(f=0;f<4;f++) + if (pressed[f]>0) + pressed[f]++; + + pressed[DOWN]=1; + dir=DOWN; + break; + + case XK_Right: + for(f=0;f<4;f++) + if (pressed[f]>0) + pressed[f]++; + + pressed[RIGHT]=1; + dir=RIGHT; + break; + + case XK_Q: + case XK_q: + dir=NONE; + return(False); + break; + + case XK_P: + case XK_p: + DoPause(); + (*Repaint)(True); + break; + + default: + dir=NONE; + } + break; + + case KeyRelease: + switch(XLookupKeysym((XKeyEvent *)&e,ShiftMapIndex)) + { + case XK_Shift_L: + case XK_Shift_R: + shiftrelease=True; + break; + + case XK_Up: + released[UP]=True; + break; + + case XK_Left: + released[LEFT]=True; + break; + + case XK_Down: + released[DOWN]=True; + break; + + case XK_Right: + released[RIGHT]=True; + break; + + default: + break; + } + break; + + default: + break; + } + } + + if (ok) + { + ok=CheckEnemies(); + + if ((shiftmode)&&(dir!=NONE)) + { + ok=HandlePush(dir,lev.sx+move_tbl[dir].x, + lev.sy+move_tbl[dir].y); + if (ok) + ok=Handle(AT(lev.sx,lev.sy)); + } + else + { + if(CanMove(dir)) + { + if (AT(lev.sx,lev.sy)==HEROSPR) + AT(lev.sx,lev.sy)=SPACESPR; + + lev.sx+=move_tbl[dir].x; + lev.sy+=move_tbl[dir].y; + ok=Handle(AT(lev.sx,lev.sy)); + AT(lev.sx,lev.sy)=HEROSPR; + } + else + ok=Handle(AT(lev.sx,lev.sy)); + } + } + + x=lev.sx-lev.x; + y=lev.sy-lev.y; + + if (x<10) + if (lev.x) + lev.x--; + + if (x>SCRX-10) + if (lev.x<lev.w-SCRX) + lev.x++; + + if (y<10) + if (lev.y) + lev.y--; + + if (y>(SCRY-10)) + if (lev.y<(lev.h-SCRY+1)) + lev.y++; + + HandleGenerators(); + HandleEnemies(); + HandleAmoeba(); + + Gravity(); + + if (ok) + ok=Handle(AT(lev.sx,lev.sy)); + + (*Repaint)(False); + DrawScore(); + (*Update)(); + + if (!ok) + { + if ((lev.sx==lev.ex)&&(lev.sy==lev.ey)) + dt=0; + else + dt--; + } + else + { + if (++ti==10) + { + ti=0; + if (!(--lev.time)) + { + ok=False; + dt=40; + + for(x=0;x<lev.w;x++) + for(y=0;y<lev.h;y++) + if ((AT(x,y)!=SPACESPR)&&(AT(x,y)!=TUFFWALLSPR)) + AT(x,y)=ROCKFALLSPR; + } + } + } + } + + return((lev.sx==lev.ex)&&(lev.sy==lev.ey)); +} + + +/* --------------------------------------------------------------------- */ + + +#define PAUSE_SX 30 +#define PAUSE_SY 5 +#define PAUSE_X 8 +#define PAUSE_Y 8 + +char *start_pause_map[PAUSE_SY]= + { + /* 123456789012345678901234567890 */ + " ## # # # ## ### ## ", + " # # # # # # # # # # ", + " ## ### # # # ## # # ", + " # # # # # # # # # ", + " # # # # ## ### ## " + }; + +int pause_map[PAUSE_SX][PAUSE_SY]; + +PauseFunc() + +{ + int x,y; + + (*Cls)(black); + + for(x=0;x<PAUSE_SX;x++) + for(y=0;y<PAUSE_SY;y++) + if (pause_map[x][y]) + { + (*Put)(PAUSE_X+x,PAUSE_Y+y,pause_map[x][y]++); + + if (pause_map[x][y]==NOSPR) + pause_map[x][y]=1; + } + + (*Update)(); + + return(XFUNCCONT); +} + + +DoPause() + +{ + int x,y; + + AutoOn(); + + for(x=0;x<PAUSE_SX;x++) + for(y=0;y<PAUSE_SY;y++) + if (*(start_pause_map[y]+x)=='#') + pause_map[x][y]=RND(NOSPR-1)+1; + else + pause_map[x][y]=0; + + (*Show)(PauseFunc,True,False); + + AutoOff(); +} + + +/* --------------------------------------------------------------------- */ + + +DoXGameOverLost() + +{ + (*Printf)(RND(X(SCRX)),RND(Y(SCRY)),white,"YOU'VE LOST!!!!!"); + + (*Update)(); + + return(XFUNCCONT); +} + + +XGameOverLost() + +{ + (*Show)(DoXGameOverLost,False); +} + +/* --------------------------------------------------------------------- */ + +#define NO_GW_CAST 14 +#define NO_GW_INTRO 6 +#define NO_GW_LINES 12 +#define GW_SPR_RAD 5 + +struct + { + int spr; + char *name; + } gw_cast[NO_GW_CAST]= + { + /* {SPACESPR,"The Empty Bits(?!?)"}, */ + {EARTHSPR,"The Ground"}, + {ROCKSPR,"Rock"}, + {GEMSPR,"Diamond"}, + {EXITSPR,"The Exit"}, + {BUTTSPR,"Butterfly"}, + {CHSRSPR,"Chaser"}, + {AMOEBASPR,"The Amoeba"}, + {ROCKSWSPR,"The Rock Switch"}, + {ONEUPSPR,"The 1 UP!!!"}, + {FILTERSPR,"The Filter"}, + {ROCKGENSPR,"The Rock Generator"}, + {BUTTGENSPR,"The Butterfly Generator"}, + {CHSRGENSPR,"The Chaser Generator"}, + {HEROSPR,"You!"} + }; + +char *gw_intro[NO_GW_INTRO]= + { + "Starring", + "Starring", + "Special appearance by", + "Introducing", + "Guest appearance by", + "Special guest star" + }; + +char *gw_text[NO_GW_LINES]= + { + "Congratulations!", + "You have completed", + "all the levels!!!", + " ", + "Thanks for playing!", + " ", + "DASH!", + "Written by", + "Noddybox", + " ", + "Visit me at", + "www.noddybox.demon.co.uk", + }; + +int gw_cast_no; +int gw_intro_no; +int gw_cast_x; +int gw_ang; +int NO_GW_SPR; +int gw_cast_inc; +int gw_text_no; +int gw_text_ti; + +DoXGameOverWonSmallScale() + +{ + static int la=0; + static int lx=0; + int a; + double dy; + int f; + + (*Cls)(black); + + (*Centre)(gw_text[gw_text_no],Y(3),white); + + if (++gw_text_ti==300) + { + gw_text_ti=0; + if (++gw_text_no==NO_GW_LINES) + gw_text_no=0; + } + + (*Printf)(X(SCRX)-gw_cast_x,Y(SCRY-1),white,"%s %s", + gw_intro[gw_intro_no],gw_cast[gw_cast_no].name); + + la=a=gw_ang; + lx=gw_cast_x; + for(f=0;f<NO_GW_SPR;f++) + { + dy=(double)(Y(15))-(double)(Y(GW_SPR_RAD))*si[a]; + + XPut( spr[gw_cast[gw_cast_no].spr].p, + 0,0,chsz,chsz, + gw_cast_x-X(f*2), + (int)dy); + + if ((a+=20)>359) + a-=360; + } + + if ((gw_ang+=1)>359) + gw_ang-=360; + + if ((gw_cast_x+=gw_cast_inc) > X(SCRX)+X(NO_GW_SPR*2)) + { + gw_cast_x=0; + gw_intro_no=RND(NO_GW_INTRO); + if (++gw_cast_no==NO_GW_CAST) + gw_cast_no=0; + } + + (*Update)(); + + return(XFUNCCONT); +} + + +DoXGameOverWonLargeScale() + +{ + static int la=0; + static char s[100]; + int a; + double dx,dy; + int f; + + XFillBox(0,Y(2),X(SCRX),Y(2),black); + XFillBox(0,Y(SCRY-2),X(SCRX),Y(2),black); + + a=la; + for(f=0;f<NO_GW_SPR;f++) + { + dx=(double)(X(SCRX/2))-(double)(X(GW_SPR_RAD))*si[a]; + dy=(double)(Y(SCRY/2))-(double)(Y(GW_SPR_RAD))*co[a]; + + XFillBox((int)dx,(int)dy,chsz,chsz,black); + + if ((a+=(360/NO_GW_SPR))>359) + a-=360; + } + + (*Centre)(gw_text[gw_text_no],Y(3),white); + + if (++gw_text_ti==100) + { + gw_text_ti=0; + if (++gw_text_no==NO_GW_LINES) + gw_text_no=0; + } + + sprintf(s,"%s %s",gw_intro[gw_intro_no],gw_cast[gw_cast_no].name); + (*Centre)(s,Y(SCRY-1),white); + + la=a=gw_ang; + for(f=0;f<NO_GW_SPR;f++) + { + dx=(double)(X(SCRX/2))-(double)(X(GW_SPR_RAD))*si[a]; + dy=(double)(Y(SCRY/2))-(double)(Y(GW_SPR_RAD))*co[a]; + + XPut( spr[gw_cast[gw_cast_no].spr].p, + 0,0,chsz,chsz, + (int)dx, + (int)dy); + + if ((a+=(360/NO_GW_SPR))>359) + a-=360; + } + + if ((gw_ang+=1)>359) + gw_ang-=360; + + if (++gw_cast_x==100) + { + gw_cast_x=0; + gw_intro_no=RND(NO_GW_INTRO); + if (++gw_cast_no==NO_GW_CAST) + gw_cast_no=0; + } + + (*Update)(); + + return(XFUNCCONT); +} + + +XGameOverWon() + +{ + score+=lives*2000; + + gw_cast_no=0; + gw_cast_x=0; + gw_intro_no=RND(NO_GW_INTRO); + gw_ang=0; + + gw_text_no=0; + gw_text_ti=0; + + if (chsz==8) + { + NO_GW_SPR=20; + gw_cast_inc=1; + (*Show)(DoXGameOverWonSmallScale,False); + } + else + { + NO_GW_SPR=5; + gw_cast_inc=3; + (*Show)(DoXGameOverWonLargeScale,False); + } +} + +XEndWindowing() +{ + /* X11 cleans up on exit anyway... */ +} + +/* --------------------------------------------------------------------- */ + +int CmpHi(a,b) +hiscore *a,*b; + +{ + int f; + + (*Cls)(black); + + (*Centre)("YOU GOT A HISCORE!!!!!!",Y(1),white); + + (*Printf)(0,Y(3),white,"%3s %7s %-*s %3s", + "Pos","Score",HINAMELEN,"Name","Level"); + + for(f=0;f<MAX_HISCORE;f++) + (*Printf)(0,Y(5+f),white,"%3d %7d %-*s %3d", + f+1,hisc[f].score,HINAMELEN,hisc[f].name,hisc[f].level); + + (*Update)(); + + return(b->score-a->score); +} + + +int ShowTable() + +{ + int f; + + (*Cls)(black); + + (*Centre)("YOU GOT A HISCORE!!!!!!",Y(1),white); + + (*Printf)(0,Y(3),white,"%3s %7s %-*s %3s", + "Pos","Score",HINAMELEN,"Name","Level"); + + for(f=0;f<MAX_HISCORE;f++) + (*Printf)(0,Y(5+f),white,"%3d %7d %-*s %3d", + f+1,hisc[f].score,HINAMELEN,hisc[f].name,hisc[f].level); + + (*Centre)("Press Space to continue",Y(SCRY-2),white); + + (*Update)(); +} + + +EnterHiscore() + +{ + LoadScores(); + + strncpy(hisc[MAX_HISCORE-1].name,getpwuid(getuid())->pw_name,HINAMELEN); + hisc[MAX_HISCORE-1].score=score; + hisc[MAX_HISCORE-1].level=level; + + qsort(hisc,MAX_HISCORE,sizeof(hiscore),CmpHi); + + SaveScores(); + + (*Show)(ShowTable,False); +} + +/* --------------------------------------------------------------------- */ + +int CursesCls(c) +int c; +{ + erase(); +} + + +int CursesPut(x,y,c) +int x,y,c; +{ + mvaddch(y,x,glyph_map[c]); +} + + +int CursesRedraw() +{ + move(LINES-1,COLS-1); + refresh(); +} + + +int CursesRepaint(full) +int full; + +{ + int x,y,px,py; + + if (full) + for(x=0;x<SCRX;x++) + for(y=1;y<SCRY;y++) + mvaddch(y,x,' '); + + for(y=1;y<SCRY;y++) + for(x=0;x<SCRX;x++) + { + px=lev.x+x; + py=lev.y+y-1; + + if ((px<lev.w)&&(py<lev.h)&&(px>-1)&&(py>-1)) + mvaddch(y,x,glyph_map[AT(px,py)]); + else + mvaddch(y,x,glyph_map[SPACESPR]); + } +} + + +int CursesPrintf(int x, int y, int c, const char *fmt, ...) +{ + char s[128]; + va_list l; + + va_start(l, fmt); + + vsprintf(s,fmt,l); + + mvaddstr(y,x,s); + + va_end(l); +} + + +int CursesIntroLevel() +{ + char s[128]; + + (*Cls)(black); + + sprintf(s,"Level %d",level); + (*Centre)(s,Y(3),white); + + sprintf(s,"'%s'",lev.name); + (*Centre)(s,Y(5),white); + + (*Centre)("Press Space to continue",Y(SCRY-2),white); + + (*Update)(); + + return(XFUNCCONT); +} + + +int CursesPlayLevel() +{ + int dir=NONE; + int x,y,ok,ls,kp,kpm,dt,ti; + int f,r; + int shiftmode; + + AT(lev.sx,lev.sy)=HEROSPR; + (*Cls)(black); + (*Repaint)(True); + DrawScore(); + (*Update)(); + + ok=True; + dt=20; + ti=0; + + while(dt) + { + if (slp>-1) + USLEEP(slp); + + shiftmode=False; + + switch(getch()) + { + case KEY_DOWN: + dir=DOWN; + shiftmode=False; + break; + case KEY_UP: + dir=UP; + shiftmode=False; + break; + case KEY_LEFT: + dir=LEFT; + shiftmode=False; + break; + case KEY_RIGHT: + dir=RIGHT; + shiftmode=False; + break; + + case 'X': + case 'x': + dir=DOWN; + shiftmode=True; + break; + case 'W': + case 'w': + dir=UP; + shiftmode=True; + break; + case 'A': + case 'a': + dir=LEFT; + shiftmode=True; + break; + case 'D': + case 'd': + dir=RIGHT; + shiftmode=True; + break; + + case 'p': + case 'P': + DoPause(); + break; + case 'q': + case 'Q': + return(False); + break; + default: + dir=NONE; + } + flushinp(); + + if (ok) + { + ok=CheckEnemies(); + + if (shiftmode) + { + if (dir!=NONE) + { + ok=HandlePush(dir,lev.sx+move_tbl[dir].x, + lev.sy+move_tbl[dir].y); + if (ok) + ok=Handle(AT(lev.sx,lev.sy)); + } + } + else + { + if(CanMove(dir)) + { + if (AT(lev.sx,lev.sy)==HEROSPR) + AT(lev.sx,lev.sy)=SPACESPR; + + lev.sx+=move_tbl[dir].x; + lev.sy+=move_tbl[dir].y; + ok=Handle(AT(lev.sx,lev.sy)); + AT(lev.sx,lev.sy)=HEROSPR; + } + else + ok=Handle(AT(lev.sx,lev.sy)); + } + } + + x=lev.sx-lev.x; + y=lev.sy-lev.y; + + if (x<10) + if (lev.x) + lev.x--; + + if (x>SCRX-10) + if (lev.x<lev.w-SCRX) + lev.x++; + + if (y<10) + if (lev.y) + lev.y--; + + if (y>(SCRY-10)) + if (lev.y<(lev.h-SCRY+1)) + lev.y++; + + HandleGenerators(); + HandleEnemies(); + HandleAmoeba(); + + Gravity(); + + if (ok) + ok=Handle(AT(lev.sx,lev.sy)); + + (*Repaint)(False); + DrawScore(); + (*Update)(); + + if (!ok) + { + if ((lev.sx==lev.ex)&&(lev.sy==lev.ey)) + dt=0; + else + dt--; + } + else + { + if (++ti==10) + { + ti=0; + if (!(--lev.time)) + { + ok=False; + dt=40; + + for(x=0;x<lev.w;x++) + for(y=0;y<lev.h;y++) + if ((AT(x,y)!=SPACESPR)&&(AT(x,y)!=TUFFWALLSPR)) + AT(x,y)=ROCKFALLSPR; + } + } + } + } + + return((lev.sx==lev.ex)&&(lev.sy==lev.ey)); +} + + +int _CursesGameOverWon() +{ + static unsigned int c; + + (*Cls)(black); + + c++; + + (*Centre)("Congratulations!!!",Y(2),white); + (*Centre)("You have completed",Y(3),white); + (*Centre)("dash in curses mode!!!",Y(4),white); + + (*Centre)("A feat I never thought possible...",Y(12),white); + (*Centre)("Noddybox salutes you!",Y(13),white); + (*Centre)("www.noddybox.demon.co.uk",Y(15),white); + + if ((c/10)%2) + (*Centre)("Press Space to continue",Y(SCRY-2),white); + + (*Update)(); +} + + +int CursesGameOverWon() +{ + (*Show)(_CursesGameOverWon,False,False); +} + + +int _CursesGameOverLost() +{ + static unsigned int c; + + (*Cls)(black); + + c++; + + (*Centre)("Game Over",Y(6),white); + + if ((c/10)%2) + (*Centre)("Press Space to continue",Y(SCRY-2),white); + + (*Update)(); +} + + +int CursesGameOverLost() +{ + (*Show)(_CursesGameOverLost,False,False); +} + + +int CursesDoTillPress(f,s,q) +int (*f)(); +int s,q; + +{ + chtype ch; + + while(1) + { + switch(getch()) + { + case ' ': + return; + break; + case 27: + if (q) + quit=True; + break; + default: + break; + } + + (*f)(); + + if /* (s) */ (True) + USLEEP(slp); + } +} + + +CursesEndWindowing() +{ + (*Cls)(black); + (*Update)(); + endwin(); +} + + +/* --------------------------------------------------------------------- */ + +int Exit(n) +int n; + +{ + if (EndWindowing) + (*EndWindowing)(); + exit(n); +} + +/* --------------------------------------------------------------------- */ + +#ifdef NOUSLEEP + +LocalUsleep(u) +int u; + +{ + struct timeval tv; + + tv.tv_sec=0; + tv.tv_usec=u; + + (void)select(0,NULL,NULL,NULL,&tv); +} + +#endif /* NOUSLEEP */ |