/*Smiler in Arrowe Land*/ #include #include #include #include #include #include #include #define LEVEL_SIZE 64 #define HEAP_ADDR 63488 #define UDG_ADDR 64512 #define WAIT_KEY while(!in_Inkey()); #define NUM_LEVELS 10 typedef unsigned char byte; typedef unsigned int word; //Globals long heap; char *current_map; /* level map data */ char *map[]= { "########" "#s# 3 #" "# 0 ##2#" "# # 0 #" "# 1 ##3#" "# # 1 #" "# 2 # h#" "########", "########" "#101231#" "# 2###2#" "# 32210#" "# 3s####" "# 310h #" "# 03222#" "########", "########" "# 0 #" "# 3h0# #" "#0##0#3#" "# 1 #" "# 1s1#" "# 1 #" "########", "########" "# s#" "#2#1#0##" "# 3 2 #" "#### # #" "#h3#1 #" "##3 #" "########", "########" "#h # 3 #" "# # # #" "#2#31# #" "#3 # 0 #" "#0# # #" "# #s#" "########", "########" "#1#3#3##" "# 1 #" "# 2# ##" "##3## #" "#s 12 ##" "#2# #0h#" "########", "########" "#s # #h#" "#2 1 #1#" "# # #2#" "# #02#3#" "# # 1#0#" "# 3 #" "########", "########" "# # # #" "#130100#" "#33s020#" "#2####3#" "#11h#22#" "#123001#" "########", "########" "#23021##" "#013231#" "#323#22#" "#23#323#" "#h#3111#" "##s1032#" "########", "########" "#h12030#" "#032001#" "#123012#" "#230013#" "#301230#" "#01230s#" "########", }; char *level_name[]= { "Smiley Town", "Biscuit Tin", "Cubic Mantra", "Green Elephant", "Spiffy Street", "Harlington-Straker", "Palace of Woe", "Linux Colonel", "Misty Housing Hop", "Birkenhead Market" }; //player x and y byte px,py; /*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)) /* print a 2x2 UDG number u at x,y */ void print2x2udgat64(byte x, byte y, byte u); #define print2x2udgat32(x,y,u) print2x2udgat64((x)<<1,(y),(u)) /* print a colour 2x2 UDG number u at x,y */ void printcol2x2udgat64(byte i, byte p, byte f, byte b, byte x, byte y, byte u); #define printcol2x2udgat32(i,p,f,b,x,y,u) printcol2x2udgat64((i),(p),(f),(b),(x)<<1,(y),(u)) /* 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_session(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); /* redraw the map pointed to by m*/ void redraw_map(char *m); /*semi-optimised version of above function which is called many times in the main game loop*/ void fast_printcol2x2udgat64(byte i, byte p, byte x, byte y, byte u); #define fast_printcol2x2udgat32(i,p,x,y,u) fast_printcol2x2udgat64((i),(p),(x)<<1,(y),(u)); /*rotate the arrows on the board */ void rotate_arrows(char *m); /*Print the intro screen*/ void intro_screen(void); /* Set the status line */ void set_status_line(char *s); main() { byte i,level_over, session_over,level,home_flag; init_session(); roswell: session_over=0; level=1; //for playtesting //level=NUM_LEVELS; while(!session_over) { intro_screen(); init_game(); levelstart: init_level(level); home_flag=0;level_over=0; // main game loop while(!level_over) { byte k,nx,ny,c,ok; char temp[32]; //main game loop redraw_map(current_map); fast_printcol2x2udgat32(0,6,px,py,148); if(home_flag) { set_status_line("Level Complete!"); for(i=0;i<7;i++) bit_fx(4); level_over=1; level++; } k=in_Inkey(); if(k=='r') { set_status_line("Restarting level!"); for(i=0;i<1;i++) bit_fx4(3); level_over=1; } nx=px+(((k=='p')-(k=='o'))<<1); ny=py+(((k=='a')-(k=='q'))<<1); c=current_map[(ny<<2)+(nx>>1)]; //Debugging //sprintf(temp,"%d %d %d %d %d \0",px,py,nx,ny,(int)c); //printstrat32(0,18,temp) ok=0; if(c>='0'&&c<='3') { ok=((c=='0')&&(k=='q'))||((c=='1')&&(k=='p'))|| ((c=='2')&&(k=='a'))||((c=='3')&&(k=='o')); } if(c==32||c=='h'||ok) { px=nx; py=ny; if(ok) { rotate_arrows(current_map); bit_fx(6); } if(c=='h') home_flag=1; } } if(level<=NUM_LEVELS) { goto levelstart; } else { set_status_line("Congrats! Entire game completed!"); for(i=0;i<3;i++) bit_fx2(4); printf("PRESS A KEY"); WAIT_KEY; goto roswell; } } } 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 print2x2udgat64(byte x, byte y, byte u) { char t[3]; t[2]=0; t[0]=u++;t[1]=u++; putchar(22);putchar(32+y);putchar(32+x); printf("%s",t); putchar(22);putchar(33+y);putchar(32+x); t[0]=u++;t[1]=u++; printf("%s",t); } void printcol2x2udgat64(byte i, byte p, byte f, byte b, byte x, byte y, byte u) { setcolattr(i,p,f,b); print2x2udgat64(x,y,u); } void fast_printcol2x2udgat64(byte i, byte p, byte x, byte y, byte u) { putchar(16); putchar(i|0x30); //ink putchar(17); putchar(p|0x30); //paper putchar(22);putchar(32+y);putchar(32+x);putchar(u++);putchar(u++); putchar(22);putchar(33+y);putchar(32+x);putchar(u++);putchar(u++); } 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_border(o); } void setcolmode(byte m) { putchar(1);putchar(m); } void init_session(void) { //Inititialise the heap mallinit(); // set heap as currently empty sbrk(HEAP_ADDR,1024); // add a 1K heap //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); //setup UDGs //house sprite set_udg(128,1,3,7,15,31,63,127,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); //up-arrow sprite set_udg(132,0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0xc0); set_udg(133,0xff,0x7f,0x3f,0x1f,0x0f,0x07,0x03,0x03); set_udg(134,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xff,0xff); set_udg(135,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0xff,0xff); //right-arrow sprite set_udg(136,0xff,0xff,0xff,0xff,0xff,0xff,0xc0,0xc0); set_udg(137,0xff,0xff,0x3f,0x1f,0x0f,0x07,0x03,0x01); set_udg(138,0xc0,0xc0,0xff,0xff,0xff,0xff,0xff,0xff); set_udg(139,0x01,0x03,0x07,0x0f,0x1f,0x3f,0xff,0xff); //down-arrow sprite set_udg(140,0xff,0xff,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc); set_udg(141,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f); set_udg(142,0xc0,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff); set_udg(143,0x03,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff); //left-arrow sprite set_udg(144,0xff,0xff,0xfc,0xf8,0xf0,0xe0,0xc0,0x80); set_udg(145,0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x03); set_udg(146,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xff,0xff); set_udg(147,0x03,0x03,0xff,0xff,0xff,0xff,0xff,0xff); //Smiley face set_udg(148,0xff,0xfc,0xe0,0xc0,0xc0,0xcc,0x8c,0x80); set_udg(149,0xff,0x3f,0x07,0x03,0x03,0x33,0x31,0x01); set_udg(150,0x81,0x91,0xd0,0xc8,0xc6,0xe1,0xfc,0xff); set_udg(151,0x81,0x89,0x0b,0x13,0x63,0x87,0x3f,0xff); //blank sprite set_udg(252,0,0,0,0,0,0,0,0); set_udg(253,0,0,0,0,0,0,0,0); set_udg(254,0,0,0,0,0,0,0,0); set_udg(255,0,0,0,0,0,0,0,0); //Set 32 column mode setcolmode(32); // Set the screen to black background and border colborcls(0,0,0,0,0); //Allocate memory for current map if(!(current_map=malloc(LEVEL_SIZE))) { bombout("Insufficient RAM"); } } void init_game(void) { //Set 32 column mode for main game setcolmode(32); // Set the screen to black background and white border colborcls(0,0,0,0,7); } void init_level(byte l) { char s[32]; memcpy(current_map, map[l-1],LEVEL_SIZE); sprintf(s,"Level %d: %s\0",l,level_name[l-1]); set_status_line(s); } void bombout(char *s) { setcolmode(64); colborcls(1,0,0,1,0); puts("Fatal Error:"); puts(s); exit(0); } void redraw_map(char *m) { byte i,x,y; for(i=0;i>2)&0x0e; switch(m[i]) { case '#': fast_printcol2x2udgat32(2,0,x,y,128); //house break; case '0': case '1': case '2': case '3': fast_printcol2x2udgat32(5,3,x,y,132+((m[i]&0x0f)<<2)); //arrow break; case 's': //smiley man //This now printed elsewhere //printcol2x2udgat32(0,6,0,1,x,y,148); px=x; //set starting position py=y; m[i]=' '; //blank the smiley off the current map break; case 'h': //home fast_printcol2x2udgat32(4,0,x,y,128); break; default: fast_printcol2x2udgat32(0,0,x,y,252); //blank space break; } } } void rotate_arrows(char *m) { byte i; for(i=0;i='0'&&m[i]<='3') m[i]='0'+((m[i]+1)&3); } void intro_screen(void) { byte i; setcolmode(64); //64 column mode colborcls(1,5,0,1,7); //clear screen and set border puts("Smiler in Arrowe Land"); puts("------ -- ------ ----\n"); puts("You must use q,a,o,p keys to move the Smiler character around"); puts("Arrowe Land. The goal is to get home to your green-painted house"); puts("Red painted houses act as barriers.\n"); puts("You may only move onto an arrow in the direction specified."); puts("You can move off an arrow in any direction.\n"); puts("Moving onto an arrow causes all arrows on the level to rotate"); puts("clockwise.\n"); puts("Press 'r' to restart the level when you get trapped.\n"); for(i=1;i<4;i++) bit_fx(i<<1); puts("PRESS A KEY TO START"); WAIT_KEY; } void set_status_line(char *s) { printcolstrat32(7,0,0,1,0,18, " "); printcolstrat32(7,0,0,1,0,18,s); }