Blame | Last modification | View Log | RSS feed
/*--------------------------------------------------------------*/
/* SIMULATION OF THE HUNGRY SNAKE'S GAME */
/* AUTHOR : SUNDARA PRABU THESINGU RAJAN
EMAIL : Y2KPRABU@YAHOO.COM
DEVELOPED SYSTEM : AMD DURON 1.1GHz 128MB RAM SVGA MONITOR
OS : SHARK
GCC : 3.1 (DJGPP VERSION)
UNDER THE GUIDANCE OF PROFESSORS:
Mr. Giorgio Buttazzo <giorgio@sssup.it>
Mr. Giuseppe Lipari <lipari@sssup.it>
Mr. Paolo Gai <pj@gandalf.sssup.it>
/*--------------------------------------------------------------*/
#include <kernel/kern.h>
#include <drivers/glib.h>
#include <modules/pc.h>
#include <drivers/keyb.h>
#include <semaphore.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#define XMIN 40
#define XMAX 600
#define YMIN 100
#define YMAX 450
#define D 3 /* SNAKE RADIUS */
#define ESC 27 /* ASCII code of ESCAPE key */
#define SNGROUP 1
#define FRUIT_WCET 200 //WCET FOR FRUIT
#define FRUIT_T 4000000 //PERIOD FOR FRUIT
#define SN_WCET 4000 //WCET FOR SNAKE
#define SN_T 40000 //PERIOD FOR SNAKE
#define FGROUP 2
PID pid1,pid2,pid3;
sem_t mutex;
int dx1,dy1,dx2,dy2; // WHICH DEF NEXT POS OF SNAKE
int scr[XMAX][YMAX]={{0},{0}}; // init all to zero
void assockey();
void endgame();
void pk1(KEY_EVT *KP);
// FUNCTION WHICH DRAWS SNAKES
void draw_sn(int x, int y, int c)
{
sem_wait(&mutex);
//grx_rect(x, y,x+5,y+5,c);//x+dx1*D,y+dy1*D, c);
grx_circle(x,y,D,c);
sem_post(&mutex);
}
// FRUIT TASK/THREAD WHICH RANDOMLY APPEARS AND DISAPPEARS
TASK FRUIT(void *arg)
{
int xrnd = rand()%(XMAX-10),ox=5;
int yrnd = rand()%(YMAX-10),oy=5;
int colrnd = rand()%15;
time_t seed;
seed=sys_gettime(0);
srand(seed); // RANDOMIZING POSITION OF FRUIT
while(1)
{
xrnd = rand()%(XMAX-10);
yrnd = rand()%(YMAX-10);
if ((xrnd > XMIN) &&(yrnd > YMIN)&& (scr[xrnd][yrnd]!=1))
{
sem_wait(&mutex);
grx_disc(ox,oy,4,80); // ERASE OLD FRUIT
grx_disc(xrnd,yrnd,4,colrnd); //PRINT NEW FRUIT
sem_post(&mutex);
colrnd = rand()%80;
ox=xrnd; // STORE OLD X AND OLD Y POS TO ERASE OLD FRUIT
oy=yrnd;
}
task_endcycle();
}
return(0);
}
// KEY HANDLER FOR PLR1
void kp1(KEY_EVT *keypr)
{
switch(keypr->ascii)
{ //grx_text(keypr->ascii, XMIN, YMENU+400, 1, 0);
case 's':
// grx_text("S Up pressed", XMIN, YMENU+450, 14, 0);
dx1=0;
dy1=-1;
break;
case 'x':
// grx_text("X Down pressed", XMIN, YMENU+450, 14, 0);
dx1=0;
dy1=1;
break;
case 'c':
// grx_text("C Right pressed", XMIN, YMENU+450, 14, 0);
dx1=1;
dy1=0;
break;
case 'z':
// grx_text("Z Left pressed", XMIN, YMENU+450, 14, 0);
dx1=-1;
dy1=0;
break;
}
}
// KEYHANDLER FOR PLR 2
void kp2(KEY_EVT *keypr)
{ switch(keypr->ascii)
{
case 'k':
// grx_text("k Up Pressed", 450, YMENU+450, 14, 0);
dx2=0;
dy2=-1;
break;
case 44:
// grx_text(", Down Pressed",450, YMENU+450, 14, 0);
dx2=0;
dy2=1;
break;
case 46:
// grx_text(". Right Pressed",450, YMENU+450, 14, 0);
dx2=1;
dy2=0;
break;
case 'm':
// grx_text("m Left Pressed", 450, YMENU+450, 14, 0);
dx2=-1;
dy2=0;
break;
}
}
// ASSOCIATE KEYS WITH PLAYER1
void assockey1()
{
KEY_EVT k;
k.flag = 0;
k.scan = KEY_S ;// UP
k.ascii = 's';
keyb_hook(k,kp1);
k.flag = 0; // DOWN
k.scan = KEY_X;
k.ascii = 'x';
keyb_hook(k,kp1);
k.flag = 0;
k.scan = KEY_Z; //LEFT
k.ascii = 'z';
keyb_hook(k,kp1);
k.flag = 0;
k.scan = KEY_C; //RIGHT
k.ascii = 'c';
keyb_hook(k,kp1);
}
// ASSOCIATE KEYS WITH PLAYER2
void assockey2()
{
KEY_EVT k;
k.flag =0;
k.scan =KEY_K;//UP
k.ascii=53;
keyb_hook(k,kp2);
k.flag = 0;
k.scan = 51;//DOWN
k.ascii = ',';
keyb_hook(k,kp2);
k.flag = 0;
k.scan = KEY_M;//LEFT
k.ascii = 'm';
keyb_hook(k,kp2);
k.flag = 0; //RIGHT
k.scan = 52;
k.ascii = '.';
keyb_hook(k,kp2);
}
// TASK SNAKE 1 .. PLAYER 1
TASK sn1(void *arg)
{
int x1, y1;
long score1 =0;
int col,outx=0,outy=0;
//int i = (int)arg;
int over1=0;
char strk[30];
x1 = XMIN+20;
y1 = (YMIN+YMAX)/2;
dx1=1;
dy1=0;
assockey1(); // CALL FN to ASSOCIATE KEYS PLR1
col = 12; /* RED COLOUR SNAKE */
while (1)
{
x1 += dx1;
y1 += dy1;
//CHECK IF BEYOND BORDER
outx = (x1 >= XMAX-D) || (x1 <= XMIN+D);
outy = (y1 >= YMAX-D) || (y1 <= YMIN+D);
//CHECK IF STONE OR ANOTHER SNAKE
if ((scr[x1+D*dx1][y1+D*dy1]) ==0)
{ scr[x1][y1]=1; // bcos the snake radius is 3;
scr[x1+dy1][y1+dx1] =1;
scr[x1-dy1][y1-dx1] =1;
}
else //STONE OR SNAKE HIT
{ over1=1; //SET ERR FLAG=1
sprintf(strk,"PLR 1 HIT :PID = %d",pid1);
}
if (outx || outy) // WALL CRASH
{
sprintf(strk,"PLR 1 WALL CRASH %d ",pid1);
over1=1;
}
if (over1 ==1) //CHECK IF HIT OR CRASH DECLARE OTHER AS WINNER
{grx_text(strk, 120,70,0,69);
grx_text(" WINNER !!! ",340+80,70,0,67);
endgame();
break;
}
score1=score1+10;
// CHECK IF BACKGROUND COLOUR OR FRUIT
if (grx_getpixel(x1+D*dx1,y1+D*dy1)!= 80)
score1+=100; // BONUS = 1000
sprintf(strk,"%ld",score1);
grx_text(strk,120,60,0,15);//PRINT SCORE
draw_sn(x1, y1, col);
task_endcycle();
}
return(0);
}
// TASK SNAKE2 -- PLAYER 2
TASK sn2(void *arg)
{
int x2, y2,col;
long int score2=0;
int outx=0, outy=0;
//int i = (int)arg;
int over2=0;
char strk[30];
assockey2();
x2 = XMAX-20;
y2 = (YMIN+YMAX)/2;
dx2=-1;
dy2=0;
col =10; /* BLUE colore SNAKE2 */
while (1)
{
x2 += dx2; //SET NEW POS
y2 += dy2;
// //CHECK IF BEYOND BORDER
outx = (x2 >= XMAX-D) || (x2 <= XMIN+D);
outy = (y2 >= YMAX-D) || (y2 <= YMIN+D);
//CHECK IF STONE OR ANOTHER SNAKE
if ((scr[x2+D*dx2][y2+D*dy2]) ==0)
{ scr[x2][y2]=1; // bcos the snake radius is 3;
scr[x2+dy2][y2+dx2] =1;
scr[x2-dy2][y2-dx2] =1;
}
else //STONE OR SNAKE HIT
{
over2=1; //SET ERR FLAG
sprintf(strk," HIT :PID = %d",pid2);
grx_text(strk,340+80,70,0,67);
}
if (outx || outy) // WALL CRASH
{
over2=1;
sprintf(strk," WALL CRASH PID= %d",pid2);
}
if(over2==1) //DECLARE OTHER AS WINNER
{ grx_text(strk,340+80,70,0,67);
grx_text(" WINNER !!! ",120,70,0,69);
endgame();
break;
}
score2=score2+10;
if (grx_getpixel(x2+D*dx2,y2+D*dy2)!= 80)
score2+=100;
sprintf(strk,"%ld",score2);
grx_text(strk,340+80,60,0,15);//
draw_sn(x2, y2, col);
sprintf(strk,"%d",scr[x2][y2]);
task_endcycle();
}
return(0);
}
/****************************************************************/
void endgame()
{ group_kill(SNGROUP);// KILL ALL SNAKES AND FRUIT TASK
grx_clear(1);
grx_text("THANK U FOR PLAYING SNAKES GAME ",200,250,14,1);
grx_text("PRESS ESC KEY ",250,300,14,1);
}
/* FN CALLED WHEN SYSTEM EXITS */
void byebye(void *arg)
{
grx_close();
kern_printf("\nCiao ! Bye Bye!\n");
}
// FN TO DRAW STONES
void stone(int xmin,int ymin,int xmax,int ymax,int col)
{ int i,j;
grx_box(xmin,ymin,xmax,ymax,col);
grx_rect(xmin,ymin,xmax,ymax,0);
for(i=xmin;i<=xmax;i++)
for(j=ymin;j<=ymax;j++)
{scr[i][j]=1; // col
}
}
void setplarea()
{ int i,j;
char col[2];
// SET SCR ARRAY WHICH REPRESENTS BG TO ZERO ALL
for(i=0;i<=XMAX-1;i++)
for(j=0;j<=YMAX-1;j++)
scr[i][j]=0;
/* GRAPHICS FOR THE PLAY AREA */
grx_box(0,0,640,480,15); // FULL SCREEN
grx_rect(XMIN-D, YMIN-1, XMAX+1, YMAX+1,1); // BOUNDARY
grx_box(XMIN,YMIN,XMAX,YMAX,80); //PLAY AREA
// DRAW STONES
stone(120,150,140,160,4);
stone(220,150,230,170,4);
stone(340,150,360,160,4);
stone(500,150,510,170,4);
stone(100,240,110,260,4);
stone(300,250,320,260,4);
stone(550,250,560,270,4);
stone(350,270,370,280,4);
stone(50, 410,70,420,4);
stone(250,400,260,420,4);
stone(370,400,390,410,4);
stone(490,400,500,420,4);
stone(150,400,170,410,4);
stone(60,300,80,310,4);
stone(530,200,550,210,4);
stone(510,300,520,320,4);
// CREATE BACKGROUND
grx_text(" SIMULATION OF SNAKES GAME ", XMIN+200,10,9,15);
grx_text(" 1 . SPACE : START GAME SnakeS" , XMIN, 20,4,15);
grx_text(" 2 . ESC : Exit to DOS ", 380, 20,2,15);
// PLAYER 1 STATISTICS
grx_box(XMIN,50,320,80,69);
grx_rect(XMIN-2,50-2,320,80,0);
grx_text(" PLAYER 1 ", XMIN, 50, 0, 69);
grx_text(" SCORE : " , XMIN, 60, 0, 69);
grx_text(" STATUS : " , XMIN, 70, 0, 69);
grx_text("UP - s",80,460, 0, 69);
grx_text("DOWN - x",80,470, 0, 69);
grx_text("LEFT - z",200,460, 0, 69);
grx_text("RIGHT - c",200,470, 0, 69);
// PLAYER 2 STATISTICS
grx_box(340,50,600,80,67);
grx_rect(340-2,50-2,600,80,0);
grx_text(" PLAYER 2 " , 340, 50, 1, 67);
grx_text(" SCORE : " , 340, 60, 1, 67);
grx_text(" STATUS : " , 340, 70, 1, 67);
grx_text("UP - k",380,460, 1, 67);
grx_text("DOWN - ,",380,470, 1, 67);
grx_text("LEFT - m",500,460, 1, 67);
grx_text("RIGHT - .",500,470, 1, 67);
// DESIGN
for(i=0,j=0;i<=60;i++)
{
j=j+10;
sprintf(col,"C%d",i);
grx_text(col,j,30,i, 0);
}
}
void initscr()
{ int i,j,col;
grx_clear(15);
for(i=0,col=0;i<640;i=i+10)
for(j=0;j<480;j=j+10)
{
// sprintf(col,"C%d",col++%255);
grx_text("",i,j,(col++)%255, 0);
}
grx_text("THE HUNGRY SNAKE ",250,100,9,15);
sleep(1);
// DISPLAY MODE SELECTION MENU SCREEN
grx_clear(8);
grx_text("THE HUNGRY SNAKE ",250,100,14,8);
grx_text("SELECT THE MODE OF PLAY ",200,150,10,8);
grx_text("1. SINGLE PLAYER MODE ",200,200,12,8);
grx_text("2. DOUBLE PLAYER MODE ",200,250,80,8);
grx_text("3. EXIT ",200,300,80,8);
}
int main(int argc, char **argv)
{
HARD_TASK_MODEL m;
SOFT_TASK_MODEL f;
char c;
int ntask = 1; /* NO OF TASKS */
hard_task_default_model(m);
hard_task_def_ctrl_jet (m);
hard_task_def_arg (m, (void *)ntask);
hard_task_def_wcet (m, SN_WCET);
hard_task_def_mit (m, SN_T);
hard_task_def_group (m, SNGROUP);
hard_task_def_unjoinable(m);
hard_task_def_usemath (m);//fl pt arith
// SOFT TASK FOR FRUIT/FRUIT
soft_task_default_model(f);
soft_task_def_level(f,1);
soft_task_def_arg(f, (void *)4);
soft_task_def_group(f,SNGROUP);
soft_task_def_met(f,FRUIT_WCET);
soft_task_def_period(f,FRUIT_T);
soft_task_def_usemath(f);
soft_task_def_unjoinable(f);
set_exchandler_grx(); /*SET EXCEPN HANDLER */
/* Set the closing function */
sys_atrunlevel(byebye, NULL, RUNLEVEL_BEFORE_EXIT);
/* graphic card Initialization */
if (grx_init() < 1)
{
cprintf("GRAPHICS INIT ERROR ,ABORTING ");
sys_abort(1);
}
grx_cardinfo(); // TO SEE THE V CARD DETAILS IN TEXT MODE
grx_modeinfo();
//sleep(2);
if (grx_open(640, 480, 8) < 0)
{
kern_printf("GRX Err CANT OPEN IN REQ MODE\n");
sys_abort(1);
}
kern_printf("Video card ok!\n");
REP:initscr(); // call FN TO DISPLAY MENU
c= keyb_getchar(); // CHOOSE GAME MODE
switch(c)
{
case '1':
grx_text("1. SINGLE PLAYER MODE ",200,350,8,0);
pid1 = task_create("SNAKE1", sn1, &m, NULL); //PLR1
break;
case '2':
pid1 = task_create("SNAKE1", sn1, &m, NULL); //PLR1
pid2 = task_create("SNAKE2",sn2,&m,NULL); //PLR2
break;
case '3':
sys_end();
return 0;
case ESC:
grx_clear(0);
grx_close();
sys_end();
return 0;
default :
grx_text("WRONG KEY PRESSED ",200,400,69,7);
goto REP;
}
setplarea(); // GRAPHICS FOR PLAY AREA
/* The program waits a space to start THE SNAKE GAME */
c = keyb_getch(NON_BLOCK);
do{
if ((c == ' '))// && (ntask < 2)) // 2 PLAYERS
{
//CHECK FOR CREATION ERRORS
if (pid1 == NIL)
{
grx_close();
perror("CANT CREATE PID1 PRESS ESC");
sys_abort(1);
}
if (pid2 == NIL)
{
grx_close();
perror("CANT CREATE PID2 PRESS ESC");
//sys_abort(1);// I HAVE COMMENTED THIS BCOS IT DOESNT SHOW MSG
// IF PID = NIL
}
if (pid3 == NIL)
{
grx_close();
perror("CANT CREATE PID3 PRESS ESC ");
//sys_abort(1);
} //ACTIVATE TASKS ;
//CREATE TASK
pid3 = task_create("FRUIT",FRUIT,&f,NULL); //FRUIT TASK
group_activate(SNGROUP);
ntask++;
}
c=keyb_getch(NON_BLOCK);
} while (c != ESC); //EXIT If ESC PRESSED
goto REP;
sys_end();
return 0;
}
/*------------------END--OVER-----------------------------------*/