/*Snake 2011 Digital Prawn */ #include #include #include #include #include #include #include #include #define UDG_ADDR 64512 #define WAIT_KEY in_WaitForKey() #define MAX_SNAKE_LENGTH 704 #define INIT_LENGTH 5 #define NUM_LEVELS 4 #define MY_ATTR(x,y) *(byte *)(0x5800+((y)<<5)+(x)) typedef unsigned char byte; typedef unsigned int word; //Globals byte snakex[MAX_SNAKE_LENGTH],snakey[MAX_SNAKE_LENGTH],score; word head,tail; char dir,dx,dy; byte level; char tempstr[32]; char *level_name[NUM_LEVELS]= {"LD","ADD","RLD","CPI"}; //For the intro/game over/game won screens byte mono_sprite0[10]={8,8,0,0,0,0,0,0,0,0}; //Function Prototypes /*Set up a UDG (numbered from 128-255) */ void set_udg(byte n,byte d0, byte d1, byte d2, byte d3, byte d4, byte d5, byte d6, byte d7); /*Print a string at x,y */ void printstrat64(byte x, byte y, char *s); #define printstrat32(x,y,s) printstrat64((x)<<1,(y),(s)) /*Set the current colour attributes */ void setcolattr(byte i, byte p, byte f, byte b); /* Print a colour string at x,y */ void printcolstrat64(byte i, byte p, byte f, byte b, byte x, byte y, char *s); #define printcolstrat32(i,p,f,b,x,y,s) printcolstrat64((i),(p),(f),(b),(x)<<1,(y),(s)) /* clear the screen */ void cls(void); /* clear the screen to a specific colour */ void colcls(byte i, byte p, byte f, byte b); /* clear the screen and set the BORDER to the specified colour o*/ void colborcls(byte i, byte p, byte f, byte b, byte o); /* set mode to either 32 or 64 columns */ void setcolmode(byte m); /* init the session */ void init_universe(void); /* init the game */ void init_game(void); /*init the level */ void init_level(byte l); /*called in the event of a fatal error */ void bombout(char *s); /*Print the intro screen*/ void intro_screen(void); /* Set the status line */ void set_status_line(char *s); /* Wrapper around zx_border() library function. zx_border2() also sets BORDCR system variable which is needed if sounds are played when the BORDER is non-white */ void zx_border2(byte b); /*Slight delay in main loop to control the speed of the game*/ void main_loop_delay(byte n); void game_over(void); void won_game(void); void print_huge_char(byte x, byte y, byte i, char c); void print_huge_string(byte x, byte y, byte i, char *s); void my_bit_fx(byte n, byte m); void place_item(void); void place_wall(void); void print_score(void); //functions return 1 if memptr emulation is correct //return 0 if incorrect byte memptr_LD_test1(); byte memptr_ADD_test1(); byte memptr_RLD_test1(); byte memptr_CPI_test1(); void play_intro_tune(void); main() { char s[32]; byte i,k,level_over,nx,ny,attr,eat; byte memptr_good; byte timer,max_time; init_universe(); //Outer loop of program while(1) { intro_screen(); init_game(); levelstart: init_level(level); level_over=0; timer=1; max_time=(5-level)*5; // main game loop while(!level_over) { //reset flags eat=0; //test memptr behaviour switch(level) { #asm di #endasm case 1: memptr_good=memptr_LD_test1(); break; case 2: memptr_good=memptr_ADD_test1(); break; case 3: memptr_good=memptr_RLD_test1(); break; case 4: memptr_good=memptr_CPI_test1(); break; default: memptr_good=1; break; #asm ei #endasm } //report memptr behaviour if(memptr_good) printcolstrat32(4,0,1,1,0,23,"MEMPTR GOOD"); else printcolstrat32(2,0,1,1,0,23,"MEMPTR BAD "); //determine snake direction k=in_Inkey(); if(k=='o') dir--; if(k=='p') dir++; dir&=7; switch(dir) { case 0: dx=0;dy=-1;break; case 1: dx=1;dy=-1;break; case 2: dx=1;dy=0;break; case 3: dx=1;dy=1;break; case 4: dx=0;dy=1;break; case 5: dx=-1;dy=1;break; case 6: dx=-1;dy=0;break; case 7: dx=-1;dy=-1;break; default:break; } //find square snake is about to move on nx=snakex[head]+dx; ny=snakey[head]+dy; //check square attr=MY_ATTR(nx,ny); //flashing object if(attr&0x80) { my_bit_fx(1,2); eat=1; score++; print_score(); place_item(); //check for level completed if((score%6)==0) level_over=2; } //any other object (wall, snake) is lethal else if(attr) level_over=1; //move snake head++; if(head==MAX_SNAKE_LENGTH) head=0; snakex[head]=nx; snakey[head]=ny; //print new head s[0]='o'; s[1]=0; printcolstrat32(5,0,0,1,snakex[head],snakey[head],s); //remove old tail unless ate an object if(!eat) { s[0]=' '; s[1]=0; printcolstrat32(0,0,0,0,snakex[tail],snakey[tail],s); tail++; if(tail==MAX_SNAKE_LENGTH) tail=0; } //if timer expired,place wall if memptr is bad if(!timer) if(!memptr_good) place_wall(); //delay main_loop_delay(150); //increment timer if(timer++==max_time) timer=0; } //end while(!level_over) if(level_over==1) game_over(); else if(level_over==2) { level++; if(level>NUM_LEVELS) { won_game(); } else goto levelstart; } } //end while(!session_over) }//end main() void set_udg(byte n, byte d0, byte d1, byte d2, byte d3, byte d4, byte d5, byte d6, byte d7) { byte *a=(byte *)UDG_ADDR+((n-128)<<3); a[0]=d0;a[1]=d1;a[2]=d2;a[3]=d3; a[4]=d4;a[5]=d5;a[6]=d6;a[7]=d7; } void printstrat64(byte x, byte y, char *s) { putchar(22);putchar(32+y);putchar(32+x); printf("%s",s); } void setcolattr(byte i, byte p, byte f, byte b) { putchar(16); putchar(i|0x30); //ink putchar(17); putchar(p|0x30); //paper putchar(18); putchar(f|0x30); //flash putchar(19); putchar(b|0x30); //bright } void printcolstrat64(byte i, byte p, byte f, byte b, byte x, byte y, char *s) { setcolattr(i,p,f,b); printstrat64(x,y,s); } void cls(void) { putchar(12); //send a form feed control } void colcls(byte i, byte p, byte f, byte b) { setcolattr(i,p,f,b); cls(); } void colborcls(byte i, byte p, byte f, byte b, byte o) { colcls(i,p,f,b); zx_border2(o); } void setcolmode(byte m) { putchar(1);putchar(m); } void init_universe(void) { //Init the sound system bit_open(); //Alter UDG address to allow full range of 128 UDGs (above heap) putchar(3);putchar(UDG_ADDR/0x0100);putchar(UDG_ADDR%0x0100); //set up UDGs set_udg(128,255,255,255,255,255,255,255,255); set_udg(129,128,192,224,240,248,252,254,255); set_udg(130,195,195,195,195,255,255,255,255); set_udg(131,255,255,15,15,15,15,15,15); //Set 32 column mode setcolmode(32); // Set the screen to black background and border colborcls(0,0,0,0,0); } void init_game(void) { //Set 32 column mode for main game setcolmode(32); // Set the screen to black background and black border colborcls(0,0,0,0,0); //set random seed to fixed value srand(1); //Set game init variables level=1; score=0; } void init_level(byte l) { int i,c; char s[32]; //Clear the play area with ATTR 0 (empty space) colborcls(0,0,0,0,0); //Draw walls s[0]=128;s[1]=0; for(i=0;i<32;i++) { printcolstrat32(4,0,0,1,i,21,s); printcolstrat32(4,0,0,1,i,0,s); } for(i=0;i<22;i++) { printcolstrat32(4,0,0,1,0,i,s); printcolstrat32(4,0,0,1,31,i,s); } //Print status line sprintf(s,"Level %d: Testing \"%s\"\0",l,level_name[l-1]); set_status_line(s); //Print score print_score(); //Init snake position and draw it s[0]='o';s[1]=0; tail=0; head=INIT_LENGTH-1; for(i=tail;i