home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d3xx
/
d343
/
snakepit.lha
/
SnakePit
/
SnakePitSrc.lzh
/
Snake_Play.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-07-04
|
12KB
|
549 lines
/*
* MKSoft SnakePit Copyright (c) 1988 by Michael Sinz
*
* Main Game-Playing part...
*/
#include "Snake.h"
#define SCREEN_BONUS 250L
#define FOOD_BONUS 125L
#define SHRINK_BONUS 5L
#define SlowSound (-200)
#define SoundSpeedUp 7
#define SOUND_3 35
#define SOUND_2 25
#define SOUND_6 15
#define SOUND_4 5
#define BIGNUM 20000
#define ExitSpeed 30000L
/*
* START_LOOKING is the number of loops without a move before the system
* starts looking for an out. After NO_MOVE_FOUND, it kills the snake.
*/
#define START_LOOKING 9
#define NO_MOVE_FOUND 18
/* This is the interval of the speed changes */
/* MAX Value: 100,000 MIN Value: 50 */
#define SPEED_UP 28000L
/* SPEED_UP_LEVEL should be 1/16th of SPEED_UP */
#define SPEED_UP_LEVEL (SPEED_UP>>4L)
#define FADE_SPEED 50000L
#define FLASH_SPEED 1000L
#define SET_DIR(x,y,z) (((x+1)<<2)+(y+1)+((z & 0x0F)<<4))
#define DIR_UP 0x04
#define DIR_DN 0x06
#define DIR_LF 0x01
#define DIR_RT 0x09
#define DIR_UP_LF 0x14
#define DIR_DN_LF 0x16
#define DIR_LF_UP 0x41
#define DIR_RT_UP 0x49
#define DIR_UP_RT 0x94
#define DIR_DN_RT 0x96
#define DIR_LF_DN 0x61
#define DIR_RT_DN 0x69
#define DONE 2
#define DEAD 3
#define OK 1
#define AM_HERE 32
static short Play_Pointer[6] = {0x0000,0x0000,0x8000,0x8000,0x0000,0x0000};
static short Play_Level;
static short Lives;
static long Score;
static short Food_Count;
static short Snake_X[1024];
static short Snake_Y[1024];
static short Snake_P[1024];
static short Snake_Head;
static short Snake_Tail;
static short Snake_Size;
static short Stall_Flag;
static short Direction_X;
static short Direction_Y;
static long MicroSpeed;
static Pit_Screen Play_Screen;
static short SoundSpeed;
static VOID Display_At(x,y,p) register short x;
register short y;
register short p;
{
register struct Image *i=&Empty;
switch (p)
{
case DROP_BRICK:
case NORMAL_BRICK: i=&Brick; break;
case MOVING_BRICK: i=&MoveBrick; break;
case GROW_FOOD: i=&GrowFood; break;
case SHRINK_FOOD: i=&ShrinkFood; break;
}
DrawImage(MyWindow->RPort,i,((long)x<<3L),((long)y<<3L));
}
static VOID Do_Wait(microSpeed) register ULONG microSpeed;
{
Time_Req.tr_time.tv_secs=0;
Time_Req.tr_time.tv_micro=microSpeed;
DoIO(&Time_Req.tr_node);
}
VOID Do_Fade()
{
register short x;
for(x=0;x<15;x++)
{
Set_Color_Level(x);
Do_Wait(FADE_SPEED);
}
Set_Color_Level(15);
}
VOID UnDo_Fade()
{
register short x;
for(x=15;x>0;x--)
{
Set_Color_Level(x);
Do_Wait(FADE_SPEED);
}
Set_Color_Level(0);
}
static VOID SetUp_Screen()
{
register short x;
register short y;
Set_Color_Level(15);
Play_Level--;
Food_Count=0;
for(x=0;x<NUM_COL;x++) for(y=0;y<NUM_ROW;y++)
{
Display_At(x,y,Play_Screen[x][y]=All_Pit_Screens[Play_Level][x][y]);
if (Play_Screen[x][y]==GROW_FOOD) Food_Count++;
}
Play_Level++;
UpDate_Status(Play_Level,Score,Lives);
UnDo_Fade();
}
static VOID Drop_Bricks()
{
register short x;
register short y;
for(x=0;x<NUM_COL;x++) for(y=0;y<NUM_ROW;y++) if (Play_Screen[x][y]==DROP_BRICK) Display_At(x,y,Play_Screen[x][y]=EMPTY_SQUARE);
}
static VOID Move_Tail()
{
register struct Image *i;
register short x;
register short y;
register short p;
Snake_Size--;
if (Snake_P[Snake_Tail])
{
p=(Play_Screen[x=Snake_X[Snake_Tail]][y=Snake_Y[Snake_Tail]])&31;
Play_Screen[x][y]=p;
Display_At(x,y,p);
}
Snake_Tail++;
Snake_Tail&=1023;
if (Snake_P[Snake_Tail])
{
switch (15 & Snake_P[Snake_Tail])
{
case DIR_RT: i=&Tail[0]; break;
case DIR_UP: i=&Tail[1]; break;
case DIR_LF: i=&Tail[2]; break;
case DIR_DN: i=&Tail[3]; break;
}
DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Tail]<<3L),((long)Snake_Y[Snake_Tail]<<3L));
}
}
static VOID Display_Snake_Head()
{
register struct Image *i;
switch (15 & Snake_P[Snake_Head])
{
case DIR_RT: i=&Head[0]; break;
case DIR_UP: i=&Head[1]; break;
case DIR_LF: i=&Head[2]; break;
case DIR_DN: i=&Head[3]; break;
}
DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
}
static VOID Move_Head(New_X,New_Y) register short New_X;
register short New_Y;
{
register short New_Head;
register struct Image *i;
Stall_Flag=0;
Score++;
Snake_Size++;
Direction_X=New_X;
Direction_Y=New_Y;
New_Head=(Snake_Head+1)&1023;
Play_Screen[Snake_X[New_Head]=Snake_X[Snake_Head]+New_X][Snake_Y[New_Head]=Snake_Y[Snake_Head]+New_Y]|=AM_HERE;
Snake_P[New_Head]=SET_DIR(New_X,New_Y,0);
switch (Snake_P[Snake_Head]=SET_DIR(New_X,New_Y,Snake_P[Snake_Head]))
{
case DIR_UP_LF:
case DIR_RT_DN: i=&Turn[0]; break;
case DIR_UP_RT:
case DIR_LF_DN: i=&Turn[1]; break;
case DIR_DN_RT:
case DIR_LF_UP: i=&Turn[2]; break;
case DIR_DN_LF:
case DIR_RT_UP: i=&Turn[3]; break;
default: i=&Body[(New_X ? (1-New_X) : (New_Y+2))]; break;
}
DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
Snake_Head=New_Head;
Display_Snake_Head();
}
static VOID New_Snake()
{
register short x;
register short y;
register short found_x=1;
register short found_y=0;
Direction_X=0;
Direction_Y=1;
Snake_Size=1;
Snake_Head=2;
Snake_Tail=0;
Snake_P[0]=Snake_P[1]=0;
for(x=0;x<NUM_COL;x+=NUM_COL-1) for(y=1;y<(NUM_ROW-1);y++) if (Play_Screen[x][y]==POPUP_BRICK)
{
found_x=x;
found_y=y;
Direction_Y=0;
Direction_X=(x ? (-1):(1) );
}
for(x=1;x<(NUM_COL-1);x++) for(y=0;y<NUM_ROW;y+=NUM_ROW-1) if (Play_Screen[x][y]==POPUP_BRICK)
{
found_x=x;
found_y=y;
Direction_X=0;
Direction_Y=(y ? (-1):(1) );
}
Play_Screen[found_x][found_y]=NORMAL_BRICK | AM_HERE;
Snake_X[Snake_Head]=found_x;
Snake_Y[Snake_Head]=found_y;
Snake_P[Snake_Head]=SET_DIR(Direction_X,Direction_Y,0);
Display_Snake_Head();
}
static short Move_Snake(New_X,New_Y) register short New_X;
register short New_Y;
{
register short x;
register short y;
short x1;
short y1;
short flag=FALSE;
if ((New_X!=Direction_X)||(New_Y!=Direction_Y))
{
if ((-New_X!=Direction_X)&&(-New_Y!=Direction_Y))
{
x=Snake_X[Snake_Head]+New_X;
y=Snake_Y[Snake_Head]+New_Y;
if ((x>=0)&&(y>=0)&&(x<NUM_COL)&&(y<NUM_ROW))
{
switch (Play_Screen[x][y])
{
case POPUP_BRICK:
case EMPTY_SQUARE:
case GROW_FOOD:
case SHRINK_FOOD:
case MOVING_BRICK: break;
default: New_X=Direction_X;
New_Y=Direction_Y;
break;
}
}
}
else
{
New_X=Direction_X;
New_Y=Direction_Y;
}
}
x=Snake_X[Snake_Head]+New_X;
y=Snake_Y[Snake_Head]+New_Y;
if ((x<0)||(y<0)||(x>=NUM_COL)||(y>=NUM_ROW)) return(DONE);
if (Play_Screen[x][y]>=AM_HERE) return(DEAD);
if (Play_Screen[x][y]==MOVING_BRICK)
{
x1=x+New_X;
y1=y+New_Y;
if ((x1>=0)&&(y1>=0)&&(x1<NUM_COL)&&(y1<NUM_ROW))
{
if (Play_Screen[x1][y1]==EMPTY_SQUARE)
{
Display_At(x1,y1,Play_Screen[x1][y1]=Play_Screen[x][y]);
Play_Screen[x][y]=EMPTY_SQUARE;
}
}
}
switch (Play_Screen[x][y])
{
case SHRINK_FOOD: Play_Screen[x][y]=EMPTY_SQUARE;
Score+=SHRINK_BONUS;
Move_Tail();
Sound_Eat(x);
if (Snake_Size)
{
Move_Head(New_X,New_Y);
Move_Tail();
}
else return(DEAD);
break;
case GROW_FOOD: Play_Screen[x][y]=EMPTY_SQUARE;
Score+=FOOD_BONUS;
Food_Count--;
Move_Head(New_X,New_Y);
Sound_Eat(x);
switch (Food_Count)
{
case SOUND_2: Sound_Play(2,BIGNUM,SoundSpeed-SOUND_2); break;
case SOUND_3: Sound_Play(3,BIGNUM,SoundSpeed-SOUND_3); break;
case SOUND_4: Sound_Play(4,BIGNUM,SoundSpeed-SOUND_4); break;
case SOUND_6: Sound_Play(6,BIGNUM,SoundSpeed-SOUND_6); break;
}
if (!Food_Count) Drop_Bricks();
break;
case POPUP_BRICK: Play_Screen[x][y]=NORMAL_BRICK;
case EMPTY_SQUARE: Move_Head(New_X,New_Y);
Sound_Move(x);
Move_Tail();
break;
}
return(OK);
}
static VOID Do_Kill_Snake()
{
Sound_Dead();
while (Snake_Size) Move_Tail();
Move_Tail();
Snake_P[(Snake_Tail+1)&1023]=0;
Move_Tail();
Do_Fade();
}
static VOID Do_Play()
{
register struct IntuiMessage *msg;
register struct MsgPort *MyPort;
register short New_X;
register short New_Y;
register UBYTE tmp;
short flag;
short move_flag;
short t_move;
MyPort=MyWindow->UserPort;
while(Lives)
{
SoundSpeed+=SoundSpeedUp;
if ((SoundPeriod-SoundSpeed)<80) SoundSpeed=SoundPeriod-80;
Sound_Play(2,BIGNUM,SlowSound);
SetUp_Screen();
New_Snake();
while (msg=(struct IntuiMessage *)GetMsg(MyPort)) ReplyMsg(msg);
flag=FALSE;
while(!flag)
{
WaitPort(MyPort);
msg=(VOID *)(MyPort->mp_MsgList.lh_Head);
if (msg->ExecMessage.mn_Node.ln_Succ)
{
if ((msg->Class==RAWKEY)||(msg->Class==MENUPICK)) flag=TRUE;
else ReplyMsg(GetMsg(MyPort));
}
}
/*
* This is the start of the playing of a single screen/man. After
* some I/O is received, we get to here and start the snake...
*/
Sound_Play(1,BIGNUM,SoundSpeed-Food_Count);
New_X=Direction_X;
New_Y=Direction_Y;
Stall_Flag=0;
while(flag)
{
UpDate_Status(Play_Level,Score,Lives);
Do_Wait(MicroSpeed);
if (Score) Score--;
Cycle_Colors();
Stall_Flag++;
if (Stall_Flag>START_LOOKING)
{
New_X=New_Y=0;
switch ((Stall_Flag+(Score>>3))&3)
{
case 0: New_X=-1; break;
case 1: New_X= 1; break;
case 2: New_Y= 1; break;
case 3: New_Y=-1; break;
}
}
while(msg=(struct IntuiMessage *)GetMsg(MyPort))
{
if (msg->Class==RAWKEY)
{
tmp=(UBYTE)msg->Code;
if (tmp==KeyList[0].raw)
{
New_X=0;
New_Y=-1;
}
else if (tmp==KeyList[1].raw)
{
New_X=0;
New_Y=1;
}
else if (tmp==KeyList[2].raw)
{
New_X=-1;
New_Y=0;
}
else if (tmp==KeyList[3].raw)
{
New_X=1;
New_Y=0;
}
}
if ((msg->Class==MENUPICK)||(tmp==RAW_ESC))
{
ClearPointer(MyWindow);
tmp=Request_Pause();
SetPointer(MyWindow,Play_Pointer,1L,1L,-1L,0L);
if (tmp>1)
{
Lives--;
flag=FALSE;
}
if (tmp>2)
{
Sound_Dead();
Lives=0;
}
}
ReplyMsg(msg);
}
if (Stall_Flag>NO_MOVE_FOUND)
{
Do_Kill_Snake();
Lives--;
flag=FALSE;
}
if (flag)
{
move_flag=Move_Snake(New_X,New_Y);
if (move_flag==DONE)
{
DrawImage(MyWindow->RPort,&Body[(Direction_X ? (1-Direction_X) : (Direction_Y+2))],((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
Sound_Finish();
while (Snake_Size)
{
Move_Tail();
Cycle_Colors();
Score+=SCREEN_BONUS;
UpDate_Status(Play_Level,Score,Lives);
Do_Wait(ExitSpeed);
}
Move_Tail();
Snake_P[(Snake_Tail+1)&1023]=0;
Do_Wait(MicroSpeed); Move_Tail();
Do_Fade();
Score+=SCREEN_BONUS;
flag=FALSE;
Lives++;
Play_Level++;
UpDate_Status(Play_Level,Score,Lives);
if (MicroSpeed>SPEED_UP_LEVEL) MicroSpeed-=SPEED_UP_LEVEL;
if (Play_Level>MAX_LEVEL) Play_Level=1;
}
else if (move_flag==DEAD)
{
Do_Kill_Snake();
Lives--;
flag=FALSE;
}
}
}
}
}
VOID Play_Game(UserSpeed) short UserSpeed;
{
register ULONG tmpIDCMP;
OffMenu(MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
OffMenu(MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
tmpIDCMP=MyWindow->IDCMPFlags;
ModifyIDCMP(MyWindow,RAWKEY|MENUPICK);
ClearPointer(MyWindow);
Play_Level=Request_SelectLevel(0);
Sound_Play(2,BIGNUM,SlowSound);
Lives=5;
Score=NULL;
SetRast(MyWindow->RPort,0L);
UpDate_Status(Play_Level,Score,Lives);
MicroSpeed=(10L-((long)UserSpeed))*SPEED_UP;
SoundSpeed=0;
SetPointer(MyWindow,Play_Pointer,1L,1L,-1L,0L);
Do_Play();
Sound_Play(2,BIGNUM,0);
ClearPointer(MyWindow);
Set_Color_Level(0);
Request_HighScores(Score);
ShowWait();
ModifyIDCMP(MyWindow,tmpIDCMP);
OnMenu (MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
OnMenu (MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
}