summaryrefslogtreecommitdiff
path: root/galax.c
diff options
context:
space:
mode:
Diffstat (limited to 'galax.c')
-rw-r--r--galax.c1888
1 files changed, 1888 insertions, 0 deletions
diff --git a/galax.c b/galax.c
new file mode 100644
index 0000000..2283765
--- /dev/null
+++ b/galax.c
@@ -0,0 +1,1888 @@
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+
+#include "Xbit.h"
+
+#define WINX 100
+#define WINY 100
+#define WINW 220
+#define WINWH 110
+#define WINH 250
+#define WINHH 125
+
+#define TAGLINE 242
+
+#define RND(x) (rand()%(x))
+
+#define ITOF(x) ((x)<<8)
+#define FTOI(x) ((x)>>8)
+
+#define AT(p,x,y) *((p)+(x)+(y)*WINW)
+
+#define HISCFILE "hisc.gal"
+
+#define CH(x,y) ((x)*SCALE),((y)*SCALE),SCALE,SCALE
+
+XSizeHints size_hints;
+int black,white;
+Display *disp;
+Window top,sub;
+Colormap cm;
+XFontStruct *font;
+XImage *img;
+char *data;
+char *coll_data;
+
+double si[3600],co[3600];
+
+static XFuncControl Key(Window w, XPressRelease s, XEvent *e);
+static XFuncControl ProcessTitle(void),ProcessIntro(void),ProcessGame(void),
+ ProcessGameOver(void),ProcessHiScore(void),
+ ProcessStartLevel(void);
+
+/* Hiscore
+*/
+#define NOHI 10
+
+typedef struct
+ {
+ char name[4];
+ int score;
+ int level;
+ double percent;
+ } HiSc;
+
+HiSc hisc[NOHI]=
+ {
+ {"A.B",10000,1,50.0},
+ {"C.D",5000,1,50.0},
+ {"E.F",3000,1,50.0},
+ {"G.H",1500,1,50.0},
+ {"I.J",1000,1,50.0},
+ {"K.L",800,1,50.0},
+ {"M.N",600,1,50.0},
+ {"O.P",400,1,50.0},
+ {"Q.R",200,1,50.0},
+ {"S.T",100,1,50.0},
+ };
+
+/* Keycontrols
+*/
+static XWindowKeyCallback key[2]=
+ {
+ {0,Key},
+ {0,NULL}
+ };
+
+#define NONE -1
+#define LEFT 0
+#define RIGHT 1
+#define FIRE 2
+#define QUIT 3
+#define PAUSE 4
+
+int inkey=NONE;
+KeySym last_keysym;
+int keymap[PAUSE+1]={False,False,False,False,False};
+
+
+/* Sprite defs
+*/
+#define SPRW 8
+#define SPRH 8
+
+#define CHXSPR(a) ((a)*SPRW)
+
+#define SPRMAXANIM 10
+#define SPRANIMFRAME 10
+
+unsigned int framectr =0;
+unsigned int sprframe =0;
+
+typedef struct
+ {
+ ulong data[SPRH][SPRW];
+ } SpriteDef;
+
+typedef struct
+ {
+ int no;
+ char data[SPRH*SPRW];
+ } CollData;
+
+typedef struct
+ {
+ int no;
+ SpriteDef *spr[SPRMAXANIM];
+ } SpriteAnim;
+
+#define NOSPR 11
+
+#define SHIP 0
+#define ABULLET 1
+#define SBULLET 2
+#define GALAX1 3
+#define GALAX2 4
+#define GALAX3 5
+#define FLAG1 6
+#define FLAG10 7
+#define ENTITY1 8
+#define ALIENUFO 9
+#define SAFESHIP 10
+
+#include "sprdef.h"
+
+
+/* Collision data codes
+*/
+#define CNONE 0
+#define CSHIP 1
+#define CALIEN 2
+#define CABULL 3
+#define CUBULLM 64
+#define CUBULL(x) (CUBULLM+(x))
+
+
+/* Alien data
+*/
+#define NOSHOT 0
+#define SISHOT 1
+#define GASHOT 2
+#define VISHOT 3
+
+typedef struct
+ {
+ int y;
+ int x;
+ int xi;
+ int yi;
+ int inuse;
+ } Shot;
+
+typedef struct
+ {
+ int alive;
+ int type;
+ Shot shot;
+ int x,y;
+ int sx,sy; /* Use for workspace for 'alternative' coords */
+ } Alien;
+
+
+#define MAXALIEN 100
+int no_aliens;
+int aliens_alive;
+
+Alien alien[MAXALIEN];
+
+
+/* Explosion FX data
+*/
+#define MAXEXP 20
+#define EXPPART 20
+#define EXPLIFE 10
+struct
+ {
+ int inuse;
+ int cx[EXPPART],cy[EXPPART],x[EXPPART],y[EXPPART];
+ } exp_fx[MAXEXP];
+
+int no_exp;
+
+
+/* Level data
+*/
+#define NOLEV 11
+
+struct
+ {
+ char *title;
+ int sx,sy;
+ int shot_type;
+ } levdata[NOLEV]=
+ {
+ {"A CLASSIC...",0,1,SISHOT},
+ {"RUN AWAY - WATCH YOUR BACK",1,-2,GASHOT},
+ {"DIZZY",0,1,SISHOT},
+ {"VICIOUS CARNIVAL DUCKS!",0,1,VISHOT},
+ {"THE ALIEN WARFLEET - WAVE 1",-1,0,GASHOT},
+ {"BOUNCY",0,1,GASHOT},
+ {"THE 1ST COLLECTIVE",0,2,SISHOT},
+ {"THE 2ND COLLECTIVE",0,2,SISHOT},
+ {"THE 3RD COLLECTIVE",0,2,GASHOT},
+ {"THE ALIEN WARFLEET - WAVE 2",-1,0,GASHOT},
+ {"THE ALIEN MOTHERBRAIN",0,1,GASHOT},
+ };
+
+
+
+/* Colour vars
+*/
+#define NOCOLS 8
+#define RNDCOL (RND(NOCOLS-2)+2)
+#define RGB(r,g,b) {(r)*255,(g)*255,(b)*255}
+
+static ulong pix[NOCOLS];
+static Colour cols[NOCOLS]=
+ {
+ RGB(0,0,0), /* BLACK */
+ RGB(255,255,255), /* WHITE */
+ RGB(255,100,100), /* RED */
+ RGB(100,255,100), /* GREEN */
+ RGB(100,100,255), /* BLUE */
+ RGB(255,255,0), /* YELLOW */
+ RGB(0,255,255), /* CYAN */
+ RGB(165,42,42) /* BROWN */
+ };
+
+#define BLACKI 0
+#define WHITEI 1
+#define REDI 2
+#define GREENI 3
+#define BLUEI 4
+#define YELLOWI 5
+#define CYANI 6
+#define BROWNI 7
+
+#define BLACK pix[BLACKI]
+#define WHITE pix[WHITEI]
+#define RED pix[REDI]
+#define GREEN pix[GREENI]
+#define BLUE pix[BLUEI]
+#define YELLOW pix[YELLOWI]
+#define CYAN pix[CYANI]
+#define BROWN pix[BROWNI]
+
+
+/* Parallax vars
+*/
+#define NOPLXST 30
+#define NOPLXPL 3
+
+struct {int x,y,c} plxst[NOPLXST][NOPLXPL];
+
+
+/* User bullet vars
+*/
+#define MAXBULL 100
+#define BULLYI -3
+
+typedef struct
+ {
+ int inuse,x,y;
+ } UserBullet;
+
+UserBullet ubull[MAXBULL];
+int bullctr=0;
+
+/* Control vars
+*/
+int NOLIVES =3;
+int NOBULL =4;
+int BULLDEL =10;
+int LEVEL =0;
+int SCORE =0;
+int PAUSESKIP =0;
+int FONT =0;
+
+int SCALE =1;
+int POKEIMG_NS(),POKEIMG_S();
+int (*POKEIMG)();
+
+
+/* Game and control vars
+*/
+#define SHXINIT WINW/2-SPRW/2
+#define SHIPY WINH-16
+#define BLYINIT SHIPY-8
+
+int quit=False;
+
+int score,level,levelndx,lives;
+int shipx,hit,miss,dead;
+int aliendead;
+
+
+int main(argc,argv)
+int argc;
+char *argv[];
+
+{
+ void IntrHandler();
+ int f,r,x,y,arg,noshm;
+ unsigned long evmask;
+
+ arg=1;
+ noshm=False;
+
+ if (argc>arg)
+ if (!strcmp(argv[arg],"-noshm"))
+ {
+ noshm=True;
+ arg++;
+ }
+
+ if (argc>arg)
+ {
+ SCALE=atoi(argv[arg]);
+
+ if (SCALE<1)
+ {
+ fprintf(stderr,"scale param must be +ve\n");
+ exit(1);
+ }
+ }
+
+ if (SCALE==1)
+ POKEIMG=POKEIMG_NS;
+ else
+ POKEIMG=POKEIMG_S;
+
+ for(f=0;f<NOPLXST;f++)
+ for(r=0;r<NOPLXPL;r++)
+ {
+ plxst[f][r].x=RND(WINW);
+ plxst[f][r].y=RND(WINH);
+ plxst[f][r].c=RNDCOL;
+ }
+
+ for(f=0;f<3600;f++)
+ {
+ si[f]=sin(M_PI/1800.0*f);
+ co[f]=cos(M_PI/1800.0*f);
+ }
+
+ umask(0);
+ srand(getpid());
+
+ size_hints.flags=PPosition|PSize|PMinSize|PMaxSize;
+ size_hints.x=WINX;
+ size_hints.y=WINY;
+ size_hints.width=size_hints.min_width=WINW*SCALE;
+ size_hints.height=size_hints.min_height=WINH*SCALE;
+ size_hints.max_width=WINW;
+ size_hints.max_height=WINH;
+
+ evmask=KeyPressMask|KeyReleaseMask;
+
+ top=OpenWin(argc,argv,argv[0],
+ WINX,WINY,WINW*SCALE,WINH*SCALE,
+ WINW*SCALE,WINH*SCALE,
+ evmask,
+ &size_hints,&black,&white);
+
+ key[0].w=top;
+
+ DisableDoubleBuffer();
+ disp=GetDisplay();
+
+ DisablePixmap();
+
+ if (noshm)
+ DisableShm();
+
+ img=CreateXImage();
+
+ if (!(coll_data=(char *)malloc(WINW*WINH)))
+ {
+ fprintf(stderr,"Couldn't malloc() collision data\n");
+ exit(1);
+ }
+
+ AllocColoursRGB(NOCOLS,pix,cols);
+
+ for(f=0;f<NOSPR;f++)
+ for(r=0;r<SPRMAXANIM;r++)
+ if (anim[f].spr[r])
+ for(x=0;x<SPRW;x++)
+ for(y=0;y<SPRH;y++)
+ anim[f].spr[r]->data[y][x]=
+ pix[anim[f].spr[r]->data[y][x]];
+
+ XAutoRepeatOff(disp);
+
+ XISetFont(FONT);
+
+ ReadScores();
+
+ XDoWindows(NULL,NULL,key,ProcessTitle);
+
+ while(!quit)
+ {
+ score=SCORE;
+ level=LEVEL;
+ levelndx=LEVEL%NOLEV;
+ lives=NOLIVES;
+ hit=0;
+ miss=0;
+
+ do
+ {
+ shipx=SHXINIT;
+ dead=False;
+
+ ClearBullets();
+ ClearExplosions();
+ ClearKeys();
+ XDoWindows(NULL,NULL,key,ProcessStartLevel);
+
+ DefineAliens();
+
+ ClearBullets();
+ ClearExplosions();
+ ClearKeys();
+ XDoWindows(NULL,NULL,key,ProcessGame);
+ } while (lives>0);
+
+ if (score>-1)
+ {
+ ClearBullets();
+ ClearExplosions();
+ ClearKeys();
+ XDoWindows(NULL,NULL,key,ProcessGameOver);
+
+ ReadScores();
+ if (score>hisc[NOHI-1].score)
+ {
+ XDoWindows(NULL,NULL,key,ProcessHiScore);
+ WriteScores();
+ }
+ }
+
+ ClearKeys();
+ XDoWindows(NULL,NULL,key,ProcessTitle);
+ }
+
+ XAutoRepeatOn(disp);
+ DestroyXImage(img);
+ XCloseDisplay(disp);
+}
+
+
+/* ----------------------------------------------- KEY AND UTILITY
+*/
+static XFuncControl Key(Window w, XPressRelease s, XEvent *e)
+{
+ if (s==XRELEASE)
+ {
+ last_keysym=XK_VoidSymbol;
+
+ switch(XLookupKeysym((XKeyEvent *)e,ShiftMapIndex))
+ {
+ case XK_Z:
+ case XK_z:
+ keymap[LEFT]=False;
+ break;
+
+ case XK_C:
+ case XK_c:
+ keymap[RIGHT]=False;
+ break;
+
+ case XK_period:
+ keymap[FIRE]=False;
+ break;
+
+ case XK_P:
+ case XK_p:
+ keymap[PAUSE]=False;
+ break;
+
+ case XK_Q:
+ case XK_q:
+ keymap[QUIT]=False;
+ break;
+
+ default:
+ keymap[NONE]=False;
+ break;
+ }
+ }
+
+ if (s==XPRESS)
+ {
+ inkey=NONE;
+
+ switch(last_keysym=XLookupKeysym((XKeyEvent *)e,ShiftMapIndex))
+ {
+ case XK_Z:
+ case XK_z:
+ inkey=LEFT;
+ break;
+
+ case XK_C:
+ case XK_c:
+ inkey=RIGHT;
+ break;
+
+ case XK_period:
+ inkey=FIRE;
+ break;
+
+ case XK_P:
+ case XK_p:
+ inkey=PAUSE;
+ break;
+
+ case XK_Q:
+ case XK_q:
+ inkey=QUIT;
+ break;
+
+ default:
+ inkey=NONE;
+ break;
+ }
+
+ if (inkey!=NONE)
+ keymap[inkey]=True;
+ }
+
+ return (XFUNCCONT);
+}
+
+
+int GetKey()
+
+{
+ int k=inkey;
+
+ if ((inkey==PAUSE)||(inkey==QUIT)||(inkey=FIRE))
+ inkey=NONE;
+
+ return(k);
+}
+
+
+KeySym RawKey()
+
+{
+ KeySym k=last_keysym;
+
+ last_keysym=XK_VoidSymbol;
+ return(k);
+}
+
+
+ClearKeys()
+{
+ int f;
+
+ inkey=NONE;
+
+ for(f=0;f<5;f++)
+ keymap[f]=False;
+}
+
+
+/* ----------------------------------------------- GRAPHICS UTILS
+*/
+Cls(plx,xi,yi,clr)
+int plx,xi,yi,clr;
+
+{
+ static unsigned int col;
+ int f,r,x,y;
+
+ if (!((framectr++)%SPRANIMFRAME))
+ {
+ sprframe++;
+
+ for(f=0;f<NOSPR;f++)
+ spr[f]=anim[f].spr[sprframe%anim[f].no];
+ }
+
+ if (clr)
+ {
+ /* memset(data,black,WINW*WINH*SCALE*SCALE); */
+ ClsXImage(img);
+ memset(coll_data,CNONE,WINW*WINH);
+ }
+
+ if (plx)
+ {
+ col++;
+
+ for(f=0;f<NOPLXST;f++)
+ for(r=0;r<NOPLXPL;r++)
+ {
+ plxst[f][r].y+=((r+1)*yi);
+
+ if (plxst[f][r].y<0)
+ plxst[f][r].y+=WINH;
+
+ if (plxst[f][r].y>=WINH)
+ plxst[f][r].y-=WINH;
+
+ plxst[f][r].x+=((r+1)*xi);
+
+ if (plxst[f][r].x<0)
+ plxst[f][r].x+=WINW;
+
+ if (plxst[f][r].x>=WINW)
+ plxst[f][r].x-=WINW;
+
+ if (!(col%10))
+ plxst[f][r].c=RNDCOL;
+
+ (*POKEIMG)(img,plxst[f][r].x,plxst[f][r].y,plxst[f][r].c);
+ }
+ }
+}
+
+
+Update()
+{
+ DrawXImage(img);
+ XSync(disp,False);
+}
+
+
+Centre(y,c,s)
+int y,c;
+char *s;
+
+{
+ XIprintf(img,CH(WINWH-strlen(s)*4,y),c,"%s",s);
+}
+
+
+POKEIMG_NS(img,x,y,c)
+XImage *img;
+int x,y,c;
+
+{
+ XPutPixel(img,x,y,c);
+}
+
+
+POKEIMG_S(img,x,y,c)
+XImage *img;
+int x,y,c;
+
+{
+ int sx,sy;
+
+ for(sx=0;sx<SCALE;sx++)
+ for(sy=0;sy<SCALE;sy++)
+ XPutPixel(img,x*SCALE+sx,y*SCALE+sy,c);
+}
+
+
+Plot(x,y,c)
+int x,y,c;
+
+{
+ if ((x>=0)&&(x<WINW)&&(y>=0)&&(y<WINH))
+ (*POKEIMG)(img,x,y,c);
+}
+
+
+Sprite(s,x,y,coll,collcode)
+int s,x,y;
+CollData *coll;
+
+{
+ int sx,sy;
+
+ if (coll)
+ coll->no=0;
+
+ for(sy=0;sy<SPRW;sy++)
+ if (((y+sy)>=0)&&((y+sy)<WINH))
+ for(sx=0;sx<SPRW;sx++)
+ if (spr[s]->data[sy][sx]!=BLACKI)
+ if (((x+sx)>=0)&&((x+sx)<WINW))
+ {
+ if (coll)
+ {
+ if (AT(coll_data,x+sx,y+sy)!=CNONE)
+ coll->data[coll->no++]=AT(coll_data,x+sx,y+sy);
+
+ AT(coll_data,x+sx,y+sy)=collcode;
+ }
+
+ (*POKEIMG)(img,x+sx,y+sy,spr[s]->data[sy][sx]);
+ }
+}
+
+
+/* ----------------------------------------------- USER BULLET UTILS
+*/
+ClearBullets()
+{
+ int f;
+
+ bullctr=0;
+
+ for(f=0;f<NOBULL;f++)
+ ubull[f].inuse=False;
+}
+
+
+NewBullet(x,y)
+int x,y;
+
+{
+ int f;
+
+ for(f=0;f<NOBULL;f++)
+ if (!ubull[f].inuse)
+ {
+ ubull[f].inuse=True;
+ ubull[f].x=x;
+ ubull[f].y=y;
+ return;
+ }
+}
+
+
+DeleteBullet(f,y)
+
+{
+ ubull[f].inuse=False;
+}
+
+
+int BulletsInUse()
+{
+ int f,c;
+
+ for(f=c=0;f<NOBULL;f++)
+ if (ubull[f].inuse)
+ c++;
+
+ return(c);
+}
+
+
+int FreeBullets()
+{
+ return(BulletsInUse()<NOBULL);
+}
+
+
+int UpdateBullets()
+{
+ CollData coll;
+ int f;
+
+ for(f=0;f<NOBULL;f++)
+ if (ubull[f].inuse)
+ {
+ Sprite(SBULLET,ubull[f].x,ubull[f].y,&coll,CUBULL(f));
+
+ if ((ubull[f].y+=BULLYI)<-8)
+ {
+ ubull[f].inuse=False;
+ miss++;
+ }
+ }
+}
+
+
+/* ----------------------------------------------- TITLE SCREEN
+*/
+static XFuncControl ProcessTitle(void)
+
+{
+ static unsigned int ctr=0;
+ static int xi[8]={ 0,-1,-1,-1, 0, 1, 1, 1};
+ static int yi[8]={ 1, 1, 0,-1,-1,-1, 0, 1};
+ int f,k;
+
+ ctr++;
+
+ Cls(True,xi[(ctr%800)/100],yi[(ctr%800)/100],True);
+
+ Centre(20,YELLOW,"GALAXY INVADERS");
+ Centre(12,YELLOW,"________________");
+ Centre(22,YELLOW,"________________");
+
+ if ((ctr/100)%2)
+ {
+ Centre(70,RNDCOL,"ALL TIME HEROES");
+ for(f=0;f<NOHI;f++)
+ XIprintf(img,CH(4,95+f*10),WHITE,
+ "%2d %-3s %8d %5.1f%% %3d",
+ f+1,hisc[f].name,hisc[f].score,
+ hisc[f].percent,hisc[f].level);
+ /*
+ XIprintf(img,CH(8,85+f*10),WHITE,
+ "%2d %3s %8d %5.1f%%",
+ f+1,hisc[f].name,hisc[f].score,hisc[f].percent);
+ */
+ }
+ else
+ {
+ Centre(100,RED," - 10 POINTS");
+ Centre(115,RED," - 20 POINTS");
+ Centre(130,RED," - 40 POINTS");
+
+ Sprite(GALAX1,7*8,100,NULL,CNONE);
+ Sprite(GALAX2,7*8,115,NULL,CNONE);
+ Sprite(GALAX3,7*8,130,NULL,CNONE);
+ }
+
+ if ((ctr/10)%2)
+ Centre(220,WHITE,"PRESS FIRE TO PLAY");
+
+ DoDebugMenu();
+
+ Update();
+
+ k=GetKey();
+
+ if (k==FIRE)
+ return(XFUNCSTOP);
+ else if (k==QUIT)
+ {
+ quit=True;
+ return(XFUNCSTOP);
+ }
+ else
+ return(XFUNCCONT);
+}
+
+
+DoDebugMenu(fl)
+
+{
+ static int debug_menu=False;
+ KeySym k;
+ int f;
+
+ if ((k=RawKey())=='r')
+ debug_menu=!debug_menu;
+
+ if (debug_menu)
+ {
+ Cls (False,0,0,True);
+
+ for(f=0;f<128;f++)
+ XIprintf(img,CH((f%20)*8,(f/20)*8),CYAN,"%c",f);
+
+ for(f=0;f<NOSPR;f++)
+ Sprite(f,f*8,80,NULL,CNONE);
+
+ XIprintf(img,CH(0,TAGLINE-56),CYAN,
+ "(f) FONT : %5d",FONT);
+ XIprintf(img,CH(0,TAGLINE-48),CYAN,
+ "(k) PAUSE==SKIP : %5d",PAUSESKIP);
+ XIprintf(img,CH(0,TAGLINE-40),CYAN,
+ "(h) SCORE : %5d",SCORE);
+ XIprintf(img,CH(0,TAGLINE-32),CYAN,
+ "(l) LIVES : %5d",NOLIVES);
+ XIprintf(img,CH(0,TAGLINE-24),CYAN,
+ "(d) GUN DELAY : %5d",BULLDEL);
+ XIprintf(img,CH(0,TAGLINE-16),CYAN,
+ "(m) NO BULLETS : %5d",NOBULL);
+ XIprintf(img,CH(0,TAGLINE-8),CYAN,
+ "(s) START LEVEL : %5d",LEVEL);
+ XIprintf(img,CH(0,TAGLINE),CYAN,
+ "(%s)",levdata[LEVEL%NOLEV].title);
+
+ XIprintf(img,CH(0,100),CYAN,"(x) SET TO DEFAULTS");
+ XIprintf(img,CH(0,108),CYAN,"(o) SET TO DEBUG");
+ XIprintf(img,CH(0,116),CYAN,"(w) SET TO SMALLER DEBUG");
+
+ switch(k)
+ {
+ case 'f':
+ FONT^=1;
+ XISetFont(FONT);
+ break;
+ case 'k':
+ PAUSESKIP=!PAUSESKIP;
+ break;
+ case 'h':
+ SCORE=hisc[0].score;
+ break;
+ case 'l':
+ if ((++NOLIVES)>10)
+ NOLIVES=1;
+ break;
+ case 'd':
+ if (BULLDEL==10)
+ BULLDEL=1;
+ else
+ BULLDEL=10;
+ break;
+ case 'm':
+ if (NOBULL==4)
+ NOBULL=MAXBULL;
+ else
+ NOBULL=4;
+ break;
+ case 's':
+ LEVEL++;
+ break;
+ case 'x':
+ SCORE=0;
+ NOLIVES=3;
+ BULLDEL=10;
+ NOBULL=4;
+ LEVEL=0;
+ break;
+ case 'o':
+ PAUSESKIP=1;
+ NOLIVES=1;
+ BULLDEL=1;
+ NOBULL=MAXBULL;
+ LEVEL=NOLEV-1;
+ SCORE=hisc[0].score;
+ break;
+ case 'w':
+ PAUSESKIP=1;
+ LEVEL=NOLEV-1;
+ break;
+ }
+ }
+}
+
+
+/* ----------------------------------------------- START LEVEL
+*/
+static XFuncControl ProcessStartLevel(void)
+{
+ char s[80];
+
+ Cls(True,levdata[levelndx].sx,levdata[levelndx].sy,True);
+
+ sprintf(s,"LEVEL %d",level+1);
+
+ Centre (50,YELLOW,s);
+ Centre (100,RED,levdata[levelndx].title);
+
+ Update();
+
+ if (GetKey()!=NONE)
+ return(XFUNCSTOP);
+
+ return(XFUNCCONT);
+}
+
+
+/* ----------------------------------------------- PLAY LEVEL
+*/
+static XFuncControl ProcessGame(void)
+
+{
+ static unsigned int ctr=0;
+ static int immune=0;
+ int f,k;
+ CollData coll;
+
+ ctr++;
+
+ k=GetKey();
+
+ if (!PAUSESKIP)
+ if (Paused(k))
+ return (XFUNCCONT);
+
+ Cls(True,levdata[levelndx].sx,levdata[levelndx].sy,True);
+
+ if (lives)
+ for(f=0;f<lives;f++)
+ Sprite(SHIP,WINW-CHXSPR(f),TAGLINE,NULL,CNONE);
+
+ if ((level+1)/10)
+ for(f=0;f<(level+1)/10;f++)
+ Sprite(FLAG10,CHXSPR(f),TAGLINE,NULL,CNONE);
+
+ if ((level+1)%10)
+ for(f=0;f<(level+1)%10;f++)
+ Sprite(FLAG1,CHXSPR((level+1)/10+f),TAGLINE,NULL,CNONE);
+
+ XIprintf(img,CH(0,0),YELLOW,"SCORE %d",score);
+
+ if (!dead)
+ {
+ if (keymap[LEFT])
+ if (shipx>1)
+ shipx-=2;
+
+ if (keymap[RIGHT])
+ if (shipx<WINW-SPRW-1)
+ shipx+=2;
+
+ if (keymap[FIRE])
+ if (bullctr==0)
+ {
+ bullctr=BULLDEL;
+ NewBullet(shipx,BLYINIT);
+ }
+ }
+
+ if (bullctr)
+ bullctr--;
+
+ MoveAliens();
+
+ UpdateBullets();
+ UpdateExplosions();
+ DrawAndKillAliens();
+
+ if (!dead)
+ {
+ if (immune)
+ Sprite(SAFESHIP,shipx,SHIPY,&coll,CSHIP);
+ else
+ Sprite(SHIP,shipx,SHIPY,&coll,CSHIP);
+
+ if ((bullctr==0)&&(FreeBullets()))
+ Sprite(SBULLET,shipx,BLYINIT,NULL,CNONE);
+
+ if (immune)
+ immune--;
+
+ if ((coll.no)&&(!immune))
+ {
+ dead=True;
+
+ for(f=0;f<5;f++)
+ {
+ NewExplosion(shipx+SPRW/2-(SPRW/2*f),SHIPY+SPRH/2,6-f);
+ NewExplosion(shipx+SPRW/2+(SPRW/2*f),SHIPY+SPRH/2,6-f);
+ NewExplosion(shipx+SPRW/2,SHIPY+SPRH/2-(SPRH/2*f),6-f);
+ }
+ }
+ }
+
+ Update();
+
+ if (k==QUIT)
+ {
+ score=-1;
+ lives=0;
+ return(XFUNCSTOP);
+ }
+
+ if ((k==PAUSE)&&(PAUSESKIP))
+ {
+ level++;
+ levelndx=(levelndx+1)%NOLEV;
+ return(XFUNCSTOP);
+ }
+
+ if ((dead)&&(no_exp==0))
+ {
+ lives--;
+
+ if (lives==0)
+ return(XFUNCSTOP);
+ else
+ {
+ shipx=SHXINIT;
+ dead=False;
+ immune=100;
+ }
+ }
+
+ if ((aliendead)&&(no_exp==0)&&(!dead))
+ {
+ level++;
+ levelndx=(levelndx+1)%NOLEV;
+
+ if ((levelndx==0)&&(level>1))
+ lives++;
+
+ return(XFUNCSTOP);
+ }
+
+ return(XFUNCCONT);
+}
+
+
+/* ----------------------------------------------- PAUSE CODE
+*/
+DoPause()
+{
+ static unsigned int c=0;
+
+ c++;
+
+ if ((c/10)%2)
+ Centre(WINH/2-4,WHITE,"PAUSED");
+ else
+ Centre(WINH/2-4,YELLOW,"PAUSED");
+
+ Update();
+}
+
+
+int Paused(k)
+int k;
+
+{
+ static int paused=False;
+
+ if (k==PAUSE)
+ paused=!paused;
+
+ if (paused)
+ DoPause();
+
+ return(paused);
+}
+
+
+/* ----------------------------------------------- GAME OVER
+*/
+static XFuncControl ProcessGameOver(void)
+{
+ static int posx=32;
+ static unsigned int ctr=0;
+
+ Cls (True,0,1,True);
+
+ ctr++;
+
+ XIprintf(img,CH(posx,32),YELLOW,"SHOTS FIRED : %6d",hit+miss);
+ XIprintf(img,CH(posx,48),YELLOW,"HIT : %6d",hit);
+ XIprintf(img,CH(posx,64),YELLOW,"MISS : %6d",miss);
+ if (hit+miss)
+ XIprintf(img,CH(posx,80),YELLOW,"PERCENTAGE : %5.1f",
+ ((double)hit/(hit+miss))*100.0);
+ else
+ XIprintf(img,CH(posx,80),YELLOW,"PERCENTAGE : 0.0");
+
+ if ((ctr/10)%2)
+ Centre(120,WHITE,"GAME OVER");
+
+ Update();
+
+ if (GetKey()==NONE)
+ return(XFUNCCONT);
+ else
+ return(XFUNCSTOP);
+}
+
+
+/* ----------------------------------------------- HI SCORES
+*/
+ReadScores()
+{
+ int fd,f;
+
+ if ((fd=open(HISCFILE,O_RDONLY))==-1)
+ return;
+
+ for(f=0;f<NOHI;f++)
+ read(fd,hisc+f,sizeof(HiSc));
+
+ close(fd);
+}
+
+
+WriteScores()
+{
+ int fd,f;
+
+ if ((fd=open(HISCFILE,O_WRONLY|O_CREAT|O_TRUNC,0777))==-1)
+ {
+ fprintf(stderr,"Failed to write hiscores!\n");
+ return;
+ }
+
+ for(f=0;f<NOHI;f++)
+ write(fd,hisc+f,sizeof(HiSc));
+
+ close(fd);
+}
+
+
+static XFuncControl ProcessHiScore(void)
+{
+ static char *hisc_let="ABCDEFGHIJKLMNOPQRSTUVWXYZ.\177";
+ static char *let;
+ static int len=0;
+ static char name[4];
+ static int first=True;
+ static int pos=0;
+ static int bounce=0;
+ int f,done=False;
+
+ if (first)
+ {
+ len=0;
+ strcpy(name,"");
+ let=hisc_let;
+ bounce=0;
+
+ for(f=NOHI-1;f>-1;f--)
+ if (hisc[f].score<score)
+ pos=f;
+
+ if (pos<NOHI-1)
+ for(f=NOHI-1;f>pos;f--)
+ hisc[f]=hisc[f-1];
+
+ strcpy(hisc[pos].name,"");
+ hisc[pos].score=score;
+ hisc[pos].level=level+1;
+ if (hit+miss)
+ hisc[pos].percent=((double)hit/(hit+miss))*100.0;
+ else
+ hisc[pos].percent=0.0;
+
+ first=False;
+ }
+
+ Cls (True,1,1,True);
+
+ Centre(16,WHITE,"CONGRATULATIONS!");
+ Centre(30,YELLOW,"ENTER YOUR INITIALS");
+ Centre(40,YELLOW,"FOR THE ALL TIME HEROES");
+
+ hisc[pos].name[len]=*let;
+ hisc[pos].name[len+1]=0;
+
+ for(f=0;f<NOHI;f++)
+ XIprintf(img,CH(4,110+f*10),(f==pos) ? (CYAN) : (RED),
+ "%2d %-3s %8d %5.1f%% %3d",
+ f+1,hisc[f].name,hisc[f].score,
+ hisc[f].percent,hisc[f].level);
+
+ if ((keymap[LEFT])&&(!bounce))
+ {
+ bounce=30;
+ if (let==hisc_let)
+ let=hisc_let+strlen(hisc_let)-1;
+ else
+ let--;
+ }
+
+ if ((keymap[RIGHT])&&(!bounce))
+ {
+ bounce=30;
+ if (!(*++let))
+ let=hisc_let;
+ }
+
+ switch (GetKey())
+ {
+ case FIRE:
+ len++;
+ break;
+ case NONE:
+ bounce=0;
+ break;
+ }
+
+ if (bounce)
+ bounce--;
+
+ Update();
+
+ if (len==3)
+ {
+ first=True;
+ return(XFUNCSTOP);
+ }
+ else
+ return(XFUNCCONT);
+}
+
+
+/* ----------------------------------------------- PARTICLE EXPLOSION ROUTINES
+*/
+ClearExplosions()
+{
+ int f;
+
+ no_exp=0;
+
+ for(f=0;f<MAXEXP;f++)
+ exp_fx[f].inuse=0;
+}
+
+
+NewExplosion(x,y,w)
+int x,y,w;
+
+{
+ int f,r;
+
+ for(f=0;f<MAXEXP;f++)
+ if (!exp_fx[f].inuse)
+ {
+ exp_fx[f].inuse=EXPLIFE*w;
+ for(r=0;r<EXPPART;r++)
+ {
+ exp_fx[f].cx[r]=x+RND(5)-2;
+ exp_fx[f].cy[r]=y+RND(5)-2;
+ exp_fx[f].x[r]=RND(5)-2;
+ exp_fx[f].y[r]=RND(5)-2;
+ }
+ no_exp++;
+ return;
+ }
+}
+
+
+UpdateExplosions()
+{
+ int f,r;
+
+ for(f=0;f<MAXEXP;f++)
+ if (exp_fx[f].inuse)
+ {
+ for(r=0;r<EXPPART;r++)
+ Plot(exp_fx[f].cx[r]+=exp_fx[f].x[r],
+ exp_fx[f].cy[r]+=exp_fx[f].y[r],
+ CYAN);
+
+ if ((--exp_fx[f].inuse)==0)
+ no_exp--;
+ }
+}
+
+
+/* ----------------------------------------------- ALIEN DEFINITION AND MOVEMENT
+*/
+int alienctr;
+int alienyi;
+int alienxi;
+
+InitAlien(f,x,y,t)
+int f,x,y,t;
+
+{
+ alien[f].alive=True;
+ alien[f].type=t;
+ alien[f].x=x;
+ alien[f].y=y;
+ alien[f].shot.inuse=False;
+}
+
+
+SinCos(cx,cy,a,rx,ry,x,y)
+int cx,cy,a,rx,ry,*x,*y;
+
+{
+ double dx,dy;
+
+ dx=cx+si[a]*rx;
+ dy=cy+co[a]*ry;
+
+ *x=(int)dx;
+ *y=(int)dy;
+}
+
+
+DefineAliens()
+{
+ int f,x,y;
+
+ alienctr=0;
+
+ switch(levelndx)
+ {
+ case 0: /* CLASSIC */
+ no_aliens=0;
+
+ for (x=0;x<10;x++)
+ for (y=0;y<3;y++)
+ {
+ InitAlien(no_aliens,x*16,y*16+50,GALAX3-y);
+ no_aliens++;
+ }
+
+ alienxi=1;
+
+ break;
+
+ case 1: /* RUN AWAY */
+ no_aliens=0;
+
+ for(f=0;f<20;f++)
+ {
+ InitAlien(no_aliens,RND(WINW-SPRW*2)+SPRW,RND(WINH/2)+WINH/4,
+ GALAX1+RND(3));
+ no_aliens++;
+ }
+
+ break;
+
+ case 2: /* DIZZY */
+ no_aliens=0;
+
+ for(y=0;y<3;y++)
+ for(x=0;x<10;x++)
+ {
+ InitAlien(no_aliens,360*x,y*20+20,GALAX3-y);
+ alien[no_aliens].sx=alien[no_aliens].x;
+ alien[no_aliens].sy=alien[no_aliens].y;
+ no_aliens++;
+ }
+
+ break;
+
+ case 3: /* CARNIVAL */
+ no_aliens=0;
+
+ for(f=0;f<WINW/10;f++)
+ {
+ InitAlien(no_aliens,f*10,WINH-120,GALAX1+RND(3));
+ no_aliens++;
+ }
+
+ break;
+
+ case 4: /* FLEET WAVE 1 */
+ no_aliens=0;
+
+ for(x=0;x<24;x++)
+ for(y=0;y<3;y++)
+ {
+ InitAlien(no_aliens,3+x*9,50+8*y,ALIENUFO);
+ no_aliens++;
+ }
+
+ break;
+
+ case 5: /* BOUNCY */
+ no_aliens=0;
+
+ for(f=0;f<20;f++)
+ {
+ InitAlien(no_aliens,RND(WINW),RND(WINH/2)+WINH/4,GALAX1);
+
+ do
+ {
+ alien[no_aliens].sx=RND(3)-1;
+ } while (alien[no_aliens].sx==0);
+
+ do
+ {
+ alien[no_aliens].sy=RND(5)-2;
+ } while (alien[no_aliens].sy==0);
+
+ no_aliens++;
+ }
+
+ break;
+
+ case 6: /* THE COLLECTIVE 1 */
+ no_aliens=0;
+
+ for(y=0;y<SPRH;y++)
+ for(x=0;x<SPRW;x++)
+ if (galax1_1.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX1);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ else if (galax1_2.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX1);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ break;
+
+ case 7: /* THE COLLECTIVE 2 */
+ no_aliens=0;
+
+ for(y=0;y<SPRH;y++)
+ for(x=0;x<SPRW;x++)
+ if (galax2_1.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX2);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ else if (galax2_2.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX2);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ break;
+
+ case 8: /* THE COLLECTIVE 2 */
+ no_aliens=0;
+
+ for(y=0;y<SPRH;y++)
+ for(x=0;x<SPRW;x++)
+ if (galax3_1.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX3);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ else if (galax3_2.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX3);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ else if (galax3_3.data[y][x]!=BLACK)
+ {
+ InitAlien(no_aliens,0,0,GALAX3);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+ no_aliens++;
+ }
+ break;
+
+ case 9: /* FLEET WAVE 2 */
+ no_aliens=0;
+
+ for (y=0;y<3;y++)
+ for (x=0;x<20;x++)
+ {
+ InitAlien(no_aliens,(WINW*x)/20,y*10+WINH/2-10,GALAX3-y);
+ no_aliens++;
+ }
+
+ break;
+
+ case 10: /* ALIEN MOTHERBRAIN */
+ no_aliens=0;
+
+ x=10;
+ y=3;
+ for(f=0;f<44;f++)
+ {
+ InitAlien(no_aliens,0,0,ENTITY1);
+ alien[no_aliens].sx=x;
+ alien[no_aliens].sy=y;
+
+ no_aliens++;
+
+ x+=y;
+
+ if ((x<10)||(x>WINW/3))
+ {
+ y=-y;
+ x+=y;
+ }
+ }
+ break;
+
+ default:
+ printf("undefined level %d?\n",levelndx);
+ exit(1);
+ }
+}
+
+
+MoveAliens()
+{
+ int f,x,y;
+ int flag=False;
+
+ alienctr++;
+
+ switch(levelndx)
+ {
+ case 0: /* CLASSIC */
+ for (f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ {
+ alien[f].x+=alienxi;
+
+ if ((alien[f].x<1)||(alien[f].x>WINW-SPRW-1))
+ flag=True;
+ }
+
+ if (flag)
+ {
+ alienxi=-alienxi;
+
+ for (f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if ((alien[f].y+=4)>WINH)
+ alien[f].y-=WINH;
+ }
+
+ break;
+
+ case 1: /* RUN AWAY */
+ for (f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if ((alien[f].y-=1)<=-SPRH)
+ alien[f].y+=WINH+SPRH;
+
+ break;
+
+ case 2: /* DIZZY */
+ for(y=f=0;y<3;y++)
+ for(x=0;x<10;x++,f++)
+ if (alien[f].alive)
+ {
+ if (y%2)
+ {
+ if ((alien[f].sx+=10)>3599)
+ alien[f].sx-=3600;
+ }
+ else
+ {
+ if ((alien[f].sx-=10)<0)
+ alien[f].sx+=3600;
+ }
+
+ SinCos(WINW/2,WINH/2,alien[f].sx,alien[f].sy*2,
+ alien[f].sy/2,&alien[f].x,&alien[f].y);
+ }
+
+ break;
+
+ case 3: /* CARNIVAL */
+ for(f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if ((alien[f].x+=(y+1))>=WINW)
+ alien[f].x-=WINW+SPRW;
+
+ break;
+
+ case 4: /* FLEET WAVE 1 */
+ break;
+
+ case 5: /* BOUNCY */
+ for(f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ {
+ alien[f].x+=alien[f].sx;
+ if ((alien[f].x<=0)||(alien[f].x>=WINW))
+ alien[f].sx=-alien[f].sx;
+
+ alien[f].y+=alien[f].sy;
+ if ((alien[f].y<=0)||(alien[f].y>=SHIPY))
+ alien[f].sy=-alien[f].sy;
+ }
+ break;
+
+ case 6: /* THE COLLECTIVE 1 */
+ for(f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if (spr[GALAX1]->data[alien[f].sy][alien[f].sx]!=BLACK)
+ {
+ alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2);
+ alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2);
+ }
+ else
+ {
+ alien[f].x=-100;
+ alien[f].y=SHIPY;
+ }
+
+ break;
+
+ case 7: /* THE COLLECTIVE 2 */
+ for(f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if (spr[GALAX2]->data[alien[f].sy][alien[f].sx]!=BLACK)
+ {
+ alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2);
+ alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2);
+ }
+ else
+ {
+ alien[f].x=-100;
+ alien[f].y=SHIPY;
+ }
+
+ break;
+
+ case 8: /* THE COLLECTIVE 3 */
+ for(f=0;f<no_aliens;f++)
+ if (alien[f].alive)
+ if (spr[GALAX3]->data[alien[f].sy][alien[f].sx]!=BLACK)
+ {
+ alien[f].x=WINW/2-(SPRW+2)*4+alien[f].sx*(SPRW+2);
+ alien[f].y=WINH/2-(SPRH+2)*4+alien[f].sy*(SPRH+2);
+ }
+ else
+ {
+ alien[f].x=-100;
+ alien[f].y=SHIPY;
+ }
+
+ break;
+
+ case 9: /* FLEET WAVE 2 */
+ for(y=f=0;y<3;y++)
+ for(x=0;x<20;x++,f++)
+ if (alien[f].alive)
+ if (y%2)
+ {
+ if ((alien[f].x+=(y+1))>=WINW)
+ alien[f].x-=WINW+SPRW;
+ }
+ else
+ {
+ if ((alien[f].x-=(y+1))<=-SPRW)
+ alien[f].x+=WINW+SPRW;
+ }
+
+ break;
+
+ case 10: /* ALIEN MOTHERBRAIN */
+ for(f=0;f<44;f++)
+ if (alien[f].alive)
+ {
+ SinCos(WINW/2,WINH/2,f*81,alien[f].sx,
+ alien[f].sx,&alien[f].x,&alien[f].y);
+
+ alien[f].sx+=alien[f].sy;
+
+ if ((alien[f].sx<10)||(alien[f].sx>WINW/3))
+ {
+ alien[f].sy=-alien[f].sy;
+ alien[f].sx+=alien[f].sy;
+ }
+ }
+ break;
+
+ default:
+ printf("undefined level %d?\n",levelndx);
+ exit(1);
+ }
+}
+
+
+CheckAlienShot(a)
+Alien *a;
+
+{
+ if ((levdata[levelndx].shot_type==NOSHOT)||(dead))
+ return;
+
+ if (a->shot.inuse)
+ return;
+
+ if (RND(200)<(1+level))
+ {
+ a->shot.inuse=True;
+
+ a->shot.x=ITOF(a->x);
+ a->shot.y=a->y+SPRH;
+
+ switch (levdata[levelndx].shot_type)
+ {
+ case VISHOT:
+ a->shot.yi=4+RND(4);
+ break;
+ default:
+ a->shot.yi=3;
+ break;
+ }
+
+ switch (levdata[levelndx].shot_type)
+ {
+ case SISHOT:
+ a->shot.xi=0;
+ break;
+
+ case VISHOT:
+ if (shipx<a->x)
+ a->shot.xi=-16*a->shot.yi;
+ else if (shipx<a->x)
+ a->shot.xi=16*a->shot.yi;
+ else
+ a->shot.xi=0;
+ break;
+
+ case GASHOT:
+ if (shipx<a->x)
+ a->shot.xi=-64;
+ else if (shipx>a->x)
+ a->shot.xi=64;
+ else
+ a->shot.xi=0;
+ break;
+
+ default:
+ a->shot.xi=0;
+ break;
+ }
+ }
+}
+
+
+DrawAndKillAliens()
+
+{
+ CollData coll;
+ int f,r;
+
+ aliendead=True;
+
+ for(f=0;f<no_aliens;f++)
+ {
+ if (alien[f].alive)
+ {
+ aliendead=False;
+
+ CheckAlienShot(&alien[f]);
+
+ Sprite(alien[f].type,alien[f].x,alien[f].y,&coll,CALIEN);
+
+ if (BulletsInUse())
+ if (coll.no)
+ for(r=0;r<coll.no;r++)
+ if (coll.data[r]&CUBULLM)
+ {
+ NewExplosion(alien[f].x+SPRW/2,alien[f].y+SPRH/2,1);
+
+ alien[f].alive=False;
+
+ switch(alien[f].type)
+ {
+ case GALAX1:
+ score+=10;
+ break;
+ case GALAX2:
+ score+=20;
+ break;
+ case GALAX3:
+ score+=40;
+ break;
+ case ALIENUFO:
+ case ENTITY1:
+ score+=50;
+ break;
+ }
+
+ DeleteBullet(coll.data[r]-CUBULLM);
+ hit++;
+ r=coll.no+1;
+ }
+ }
+
+ if (alien[f].shot.inuse)
+ {
+ aliendead=False;
+
+ alien[f].shot.x+=alien[f].shot.xi;
+ alien[f].shot.y+=alien[f].shot.yi;
+
+ if (alien[f].shot.y>WINH)
+ alien[f].shot.inuse=False;
+ else
+ Sprite(ABULLET,FTOI(alien[f].shot.x),alien[f].shot.y,
+ &coll,CABULL);
+ }
+ }
+}