home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 300-399 / ff343.lzh / SnakePit / SnakePitSrc.lzh / Snake_Play.c < prev    next >
C/C++ Source or Header  |  1988-07-04  |  12KB  |  549 lines

  1. /*
  2.  * MKSoft SnakePit  Copyright (c) 1988  by Michael Sinz
  3.  *
  4.  * Main Game-Playing part...
  5.  */
  6.  
  7. #include    "Snake.h"
  8.  
  9. #define    SCREEN_BONUS    250L
  10. #define    FOOD_BONUS    125L
  11. #define    SHRINK_BONUS    5L
  12.  
  13. #define    SlowSound    (-200)
  14. #define    SoundSpeedUp    7
  15.  
  16. #define    SOUND_3        35
  17. #define    SOUND_2        25
  18. #define    SOUND_6        15
  19. #define    SOUND_4        5
  20.  
  21. #define    BIGNUM        20000
  22.  
  23. #define    ExitSpeed    30000L
  24.  
  25. /*
  26.  * START_LOOKING is the number of loops without a move before the system
  27.  * starts looking for an out.  After NO_MOVE_FOUND, it kills the snake.
  28.  */
  29. #define    START_LOOKING    9
  30. #define    NO_MOVE_FOUND    18
  31.  
  32. /* This is the interval of the speed changes        */
  33. /* MAX Value: 100,000  MIN Value: 50            */
  34. #define    SPEED_UP    28000L
  35. /* SPEED_UP_LEVEL should be 1/16th of SPEED_UP    */
  36. #define    SPEED_UP_LEVEL    (SPEED_UP>>4L)
  37.  
  38. #define    FADE_SPEED    50000L
  39. #define    FLASH_SPEED    1000L
  40.  
  41. #define    SET_DIR(x,y,z)    (((x+1)<<2)+(y+1)+((z & 0x0F)<<4))
  42.  
  43. #define    DIR_UP    0x04
  44. #define    DIR_DN    0x06
  45. #define    DIR_LF    0x01
  46. #define    DIR_RT    0x09
  47.  
  48. #define    DIR_UP_LF    0x14
  49. #define    DIR_DN_LF    0x16
  50. #define    DIR_LF_UP    0x41
  51. #define    DIR_RT_UP    0x49
  52. #define    DIR_UP_RT    0x94
  53. #define    DIR_DN_RT    0x96
  54. #define    DIR_LF_DN    0x61
  55. #define    DIR_RT_DN    0x69
  56.  
  57. #define    DONE    2
  58. #define    DEAD    3
  59. #define    OK    1
  60. #define    AM_HERE    32
  61.  
  62. static    short    Play_Pointer[6] = {0x0000,0x0000,0x8000,0x8000,0x0000,0x0000};
  63.  
  64. static    short        Play_Level;
  65. static    short        Lives;
  66. static    long        Score;
  67.  
  68. static    short        Food_Count;
  69.  
  70. static    short        Snake_X[1024];
  71. static    short        Snake_Y[1024];
  72. static    short        Snake_P[1024];
  73.  
  74. static    short        Snake_Head;
  75. static    short        Snake_Tail;
  76. static    short        Snake_Size;
  77.  
  78. static    short        Stall_Flag;
  79.  
  80. static    short        Direction_X;
  81. static    short        Direction_Y;
  82.  
  83. static    long        MicroSpeed;
  84.  
  85. static    Pit_Screen    Play_Screen;
  86.  
  87. static    short        SoundSpeed;
  88.  
  89. static    VOID    Display_At(x,y,p)    register    short    x;
  90.                     register    short    y;
  91.                     register    short    p;
  92. {
  93. register    struct    Image    *i=&Empty;
  94.  
  95.     switch (p)
  96.     {
  97.     case DROP_BRICK:
  98.     case NORMAL_BRICK:    i=&Brick;    break;
  99.     case MOVING_BRICK:    i=&MoveBrick;    break;
  100.     case GROW_FOOD:        i=&GrowFood;    break;
  101.     case SHRINK_FOOD:    i=&ShrinkFood;    break;
  102.     }
  103.     DrawImage(MyWindow->RPort,i,((long)x<<3L),((long)y<<3L));
  104. }
  105.  
  106. static    VOID    Do_Wait(microSpeed)    register    ULONG    microSpeed;
  107. {
  108.     Time_Req.tr_time.tv_secs=0;
  109.     Time_Req.tr_time.tv_micro=microSpeed;
  110.     DoIO(&Time_Req.tr_node);
  111. }
  112.  
  113. VOID    Do_Fade()
  114. {
  115. register    short    x;
  116.  
  117.     for(x=0;x<15;x++)
  118.     {
  119.         Set_Color_Level(x);
  120.         Do_Wait(FADE_SPEED);
  121.     }
  122.     Set_Color_Level(15);
  123. }
  124.  
  125. VOID    UnDo_Fade()
  126. {
  127. register    short    x;
  128.  
  129.     for(x=15;x>0;x--)
  130.     {
  131.         Set_Color_Level(x);
  132.         Do_Wait(FADE_SPEED);
  133.     }
  134.     Set_Color_Level(0);
  135. }
  136.  
  137. static    VOID    SetUp_Screen()
  138. {
  139. register    short    x;
  140. register    short    y;
  141.  
  142.     Set_Color_Level(15);
  143.     Play_Level--;
  144.     Food_Count=0;
  145.     for(x=0;x<NUM_COL;x++) for(y=0;y<NUM_ROW;y++)
  146.     {
  147.         Display_At(x,y,Play_Screen[x][y]=All_Pit_Screens[Play_Level][x][y]);
  148.         if (Play_Screen[x][y]==GROW_FOOD) Food_Count++;
  149.     }
  150.     Play_Level++;
  151.     UpDate_Status(Play_Level,Score,Lives);
  152.     UnDo_Fade();
  153. }
  154.  
  155. static    VOID    Drop_Bricks()
  156. {
  157. register    short    x;
  158. register    short    y;
  159.  
  160.     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);
  161. }
  162.  
  163. static    VOID    Move_Tail()
  164. {
  165. register    struct    Image    *i;
  166. register        short    x;
  167. register        short    y;
  168. register        short    p;
  169.  
  170.     Snake_Size--;
  171.     if (Snake_P[Snake_Tail])
  172.     {
  173.         p=(Play_Screen[x=Snake_X[Snake_Tail]][y=Snake_Y[Snake_Tail]])&31;
  174.         Play_Screen[x][y]=p;
  175.         Display_At(x,y,p);
  176.     }
  177.     Snake_Tail++;
  178.     Snake_Tail&=1023;
  179.     if (Snake_P[Snake_Tail])
  180.     {
  181.         switch (15 & Snake_P[Snake_Tail])
  182.         {
  183.         case DIR_RT:    i=&Tail[0];    break;
  184.         case DIR_UP:    i=&Tail[1];    break;
  185.         case DIR_LF:    i=&Tail[2];    break;
  186.         case DIR_DN:    i=&Tail[3];    break;
  187.         }
  188.         DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Tail]<<3L),((long)Snake_Y[Snake_Tail]<<3L));
  189.     }
  190. }
  191.  
  192. static    VOID    Display_Snake_Head()
  193. {
  194. register    struct    Image    *i;
  195.  
  196.     switch (15 & Snake_P[Snake_Head])
  197.     {
  198.     case DIR_RT:    i=&Head[0];    break;
  199.     case DIR_UP:    i=&Head[1];    break;
  200.     case DIR_LF:    i=&Head[2];    break;
  201.     case DIR_DN:    i=&Head[3];    break;
  202.     }
  203.     DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
  204. }
  205.  
  206. static    VOID    Move_Head(New_X,New_Y)    register    short    New_X;
  207.                     register    short    New_Y;
  208. {
  209. register        short    New_Head;
  210. register    struct    Image    *i;
  211.  
  212.     Stall_Flag=0;
  213.     Score++;
  214.     Snake_Size++;
  215.     Direction_X=New_X;
  216.     Direction_Y=New_Y;
  217.     New_Head=(Snake_Head+1)&1023;
  218.     Play_Screen[Snake_X[New_Head]=Snake_X[Snake_Head]+New_X][Snake_Y[New_Head]=Snake_Y[Snake_Head]+New_Y]|=AM_HERE;
  219.     Snake_P[New_Head]=SET_DIR(New_X,New_Y,0);
  220.     switch (Snake_P[Snake_Head]=SET_DIR(New_X,New_Y,Snake_P[Snake_Head]))
  221.     {
  222.     case DIR_UP_LF:
  223.     case DIR_RT_DN:    i=&Turn[0];    break;
  224.     case DIR_UP_RT:
  225.     case DIR_LF_DN:    i=&Turn[1];    break;
  226.     case DIR_DN_RT:
  227.     case DIR_LF_UP:    i=&Turn[2];    break;
  228.     case DIR_DN_LF:
  229.     case DIR_RT_UP:    i=&Turn[3];    break;
  230.     default:    i=&Body[(New_X ? (1-New_X) : (New_Y+2))];    break;
  231.     }
  232.     DrawImage(MyWindow->RPort,i,((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
  233.     Snake_Head=New_Head;
  234.     Display_Snake_Head();
  235. }
  236.  
  237. static    VOID    New_Snake()
  238. {
  239. register    short    x;
  240. register    short    y;
  241. register    short    found_x=1;
  242. register    short    found_y=0;
  243.  
  244.     Direction_X=0;
  245.     Direction_Y=1;
  246.     Snake_Size=1;
  247.     Snake_Head=2;
  248.     Snake_Tail=0;
  249.     Snake_P[0]=Snake_P[1]=0;
  250.     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)
  251.     {
  252.         found_x=x;
  253.         found_y=y;
  254.         Direction_Y=0;
  255.         Direction_X=(x ? (-1):(1) );
  256.     }
  257.     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)
  258.     {
  259.         found_x=x;
  260.         found_y=y;
  261.         Direction_X=0;
  262.         Direction_Y=(y ? (-1):(1) );
  263.     }
  264.     Play_Screen[found_x][found_y]=NORMAL_BRICK | AM_HERE;
  265.     Snake_X[Snake_Head]=found_x;
  266.     Snake_Y[Snake_Head]=found_y;
  267.     Snake_P[Snake_Head]=SET_DIR(Direction_X,Direction_Y,0);
  268.     Display_Snake_Head();
  269. }
  270.  
  271. static    short    Move_Snake(New_X,New_Y)    register    short    New_X;
  272.                     register    short    New_Y;
  273. {
  274. register    short    x;
  275. register    short    y;
  276.         short    x1;
  277.         short    y1;
  278.         short    flag=FALSE;
  279.  
  280.     if ((New_X!=Direction_X)||(New_Y!=Direction_Y))
  281.     {
  282.         if ((-New_X!=Direction_X)&&(-New_Y!=Direction_Y))
  283.         {
  284.             x=Snake_X[Snake_Head]+New_X;
  285.             y=Snake_Y[Snake_Head]+New_Y;
  286.             if ((x>=0)&&(y>=0)&&(x<NUM_COL)&&(y<NUM_ROW))
  287.             {
  288.                 switch (Play_Screen[x][y])
  289.                 {
  290.                 case POPUP_BRICK:
  291.                 case EMPTY_SQUARE:
  292.                 case GROW_FOOD:
  293.                 case SHRINK_FOOD:
  294.                 case MOVING_BRICK:    break;
  295.                 default:        New_X=Direction_X;
  296.                             New_Y=Direction_Y;
  297.                             break;
  298.                 }
  299.             }
  300.         }
  301.         else
  302.         {
  303.             New_X=Direction_X;
  304.             New_Y=Direction_Y;
  305.         }
  306.     }
  307.     x=Snake_X[Snake_Head]+New_X;
  308.     y=Snake_Y[Snake_Head]+New_Y;
  309.     if ((x<0)||(y<0)||(x>=NUM_COL)||(y>=NUM_ROW)) return(DONE);
  310.     if (Play_Screen[x][y]>=AM_HERE) return(DEAD);
  311.     if (Play_Screen[x][y]==MOVING_BRICK)
  312.     {
  313.         x1=x+New_X;
  314.         y1=y+New_Y;
  315.         if ((x1>=0)&&(y1>=0)&&(x1<NUM_COL)&&(y1<NUM_ROW))
  316.         {
  317.             if (Play_Screen[x1][y1]==EMPTY_SQUARE)
  318.             {
  319.                 Display_At(x1,y1,Play_Screen[x1][y1]=Play_Screen[x][y]);
  320.                 Play_Screen[x][y]=EMPTY_SQUARE;
  321.             }
  322.         }
  323.     }
  324.     switch (Play_Screen[x][y])
  325.     {
  326.     case SHRINK_FOOD:    Play_Screen[x][y]=EMPTY_SQUARE;
  327.                 Score+=SHRINK_BONUS;
  328.                 Move_Tail();
  329.                 Sound_Eat(x);
  330.                 if (Snake_Size)
  331.                 {
  332.                     Move_Head(New_X,New_Y);
  333.                     Move_Tail();
  334.                 }
  335.                 else return(DEAD);
  336.                 break;
  337.     case GROW_FOOD:        Play_Screen[x][y]=EMPTY_SQUARE;
  338.                 Score+=FOOD_BONUS;
  339.                 Food_Count--;
  340.                 Move_Head(New_X,New_Y);
  341.                 Sound_Eat(x);
  342.                 switch (Food_Count)
  343.                 {
  344.                 case SOUND_2:    Sound_Play(2,BIGNUM,SoundSpeed-SOUND_2);    break;
  345.                 case SOUND_3:    Sound_Play(3,BIGNUM,SoundSpeed-SOUND_3);    break;
  346.                 case SOUND_4:    Sound_Play(4,BIGNUM,SoundSpeed-SOUND_4);    break;
  347.                 case SOUND_6:    Sound_Play(6,BIGNUM,SoundSpeed-SOUND_6);    break;
  348.                 }
  349.                 if (!Food_Count) Drop_Bricks();
  350.                 break;
  351.     case POPUP_BRICK:    Play_Screen[x][y]=NORMAL_BRICK;
  352.     case EMPTY_SQUARE:    Move_Head(New_X,New_Y);
  353.                 Sound_Move(x);
  354.                 Move_Tail();
  355.                 break;
  356.     }
  357.     return(OK);
  358. }
  359.  
  360. static    VOID    Do_Kill_Snake()
  361. {
  362.     Sound_Dead();
  363.     while (Snake_Size) Move_Tail();
  364.     Move_Tail();
  365.     Snake_P[(Snake_Tail+1)&1023]=0;
  366.     Move_Tail();
  367.     Do_Fade();
  368. }
  369.  
  370. static    VOID    Do_Play()
  371. {
  372. register    struct    IntuiMessage    *msg;
  373. register    struct    MsgPort        *MyPort;
  374. register        short        New_X;
  375. register        short        New_Y;
  376. register        UBYTE        tmp;
  377.             short        flag;
  378.             short        move_flag;
  379.             short        t_move;
  380.  
  381.     MyPort=MyWindow->UserPort;
  382.     while(Lives)
  383.     {
  384.         SoundSpeed+=SoundSpeedUp;
  385.         if ((SoundPeriod-SoundSpeed)<80) SoundSpeed=SoundPeriod-80;
  386.         Sound_Play(2,BIGNUM,SlowSound);
  387.         SetUp_Screen();
  388.         New_Snake();
  389.         while (msg=(struct IntuiMessage *)GetMsg(MyPort)) ReplyMsg(msg);
  390.  
  391.         flag=FALSE;
  392.         while(!flag)
  393.         {
  394.             WaitPort(MyPort);
  395.             msg=(VOID *)(MyPort->mp_MsgList.lh_Head);
  396.             if (msg->ExecMessage.mn_Node.ln_Succ)
  397.             {
  398.                 if ((msg->Class==RAWKEY)||(msg->Class==MENUPICK)) flag=TRUE;
  399.                 else ReplyMsg(GetMsg(MyPort));
  400.             }
  401.         }
  402.  
  403. /*
  404.  * This is the start of the playing of a single screen/man.  After
  405.  * some I/O is received, we get to here and start the snake...
  406.  */
  407.          Sound_Play(1,BIGNUM,SoundSpeed-Food_Count);
  408.         New_X=Direction_X;
  409.         New_Y=Direction_Y;
  410.         Stall_Flag=0;
  411.         while(flag)
  412.         {
  413.             UpDate_Status(Play_Level,Score,Lives);
  414.             Do_Wait(MicroSpeed);
  415.             if (Score) Score--;
  416.             Cycle_Colors();
  417.             Stall_Flag++;
  418.             if (Stall_Flag>START_LOOKING)
  419.             {
  420.                 New_X=New_Y=0;
  421.                 switch ((Stall_Flag+(Score>>3))&3)
  422.                 {
  423.                 case 0:    New_X=-1;    break;
  424.                 case 1:    New_X= 1;    break;
  425.                 case 2:    New_Y= 1;    break;
  426.                 case 3:    New_Y=-1;    break;
  427.                 }
  428.             }
  429.             while(msg=(struct IntuiMessage *)GetMsg(MyPort))
  430.             {
  431.                 if (msg->Class==RAWKEY)
  432.                 {
  433.                     tmp=(UBYTE)msg->Code;
  434.                     if (tmp==KeyList[0].raw)
  435.                     {
  436.                         New_X=0;
  437.                         New_Y=-1;
  438.                     }
  439.                     else if (tmp==KeyList[1].raw)
  440.                     {
  441.                         New_X=0;
  442.                         New_Y=1;
  443.                     }
  444.                     else if (tmp==KeyList[2].raw)
  445.                     {
  446.                         New_X=-1;
  447.                         New_Y=0;
  448.                     }
  449.                     else if (tmp==KeyList[3].raw)
  450.                     {
  451.                         New_X=1;
  452.                         New_Y=0;
  453.                     }
  454.                 }
  455.                 if ((msg->Class==MENUPICK)||(tmp==RAW_ESC))
  456.                 {
  457.                     ClearPointer(MyWindow);
  458.                     tmp=Request_Pause();
  459.                     SetPointer(MyWindow,Play_Pointer,1L,1L,-1L,0L);
  460.                     if (tmp>1)
  461.                     {
  462.                         Lives--;
  463.                         flag=FALSE;
  464.                     }
  465.                     if (tmp>2)
  466.                     {
  467.                         Sound_Dead();
  468.                         Lives=0;
  469.                     }
  470.                 }
  471.                 ReplyMsg(msg);
  472.             }
  473.             if (Stall_Flag>NO_MOVE_FOUND)
  474.             {
  475.                 Do_Kill_Snake();
  476.                 Lives--;
  477.                 flag=FALSE;
  478.             }
  479.             if (flag)
  480.             {
  481.                 move_flag=Move_Snake(New_X,New_Y);
  482.                 if (move_flag==DONE)
  483.                 {
  484.                     DrawImage(MyWindow->RPort,&Body[(Direction_X ? (1-Direction_X) : (Direction_Y+2))],((long)Snake_X[Snake_Head]<<3L),((long)Snake_Y[Snake_Head]<<3L));
  485.                     Sound_Finish();
  486.                     while (Snake_Size)
  487.                     {
  488.                         Move_Tail();
  489.                         Cycle_Colors();
  490.                         Score+=SCREEN_BONUS;
  491.                         UpDate_Status(Play_Level,Score,Lives);
  492.                         Do_Wait(ExitSpeed);
  493.                     }
  494.                     Move_Tail();
  495.                     Snake_P[(Snake_Tail+1)&1023]=0;
  496.                     Do_Wait(MicroSpeed);    Move_Tail();
  497.                     Do_Fade();
  498.                     Score+=SCREEN_BONUS;
  499.                     flag=FALSE;
  500.                     Lives++;
  501.                     Play_Level++;
  502.                     UpDate_Status(Play_Level,Score,Lives);
  503.                     if (MicroSpeed>SPEED_UP_LEVEL) MicroSpeed-=SPEED_UP_LEVEL;
  504.                     if (Play_Level>MAX_LEVEL) Play_Level=1;
  505.                 }
  506.                 else if (move_flag==DEAD)
  507.                 {
  508.                     Do_Kill_Snake();
  509.                     Lives--;
  510.                     flag=FALSE;
  511.                 }
  512.             }
  513.         }
  514.     }
  515. }
  516.  
  517. VOID    Play_Game(UserSpeed)    short    UserSpeed;
  518. {
  519. register        ULONG        tmpIDCMP;
  520.  
  521.     OffMenu(MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
  522.     OffMenu(MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
  523.  
  524.     tmpIDCMP=MyWindow->IDCMPFlags;
  525.     ModifyIDCMP(MyWindow,RAWKEY|MENUPICK);
  526.  
  527.     ClearPointer(MyWindow);
  528.     Play_Level=Request_SelectLevel(0);
  529.     Sound_Play(2,BIGNUM,SlowSound);
  530.     Lives=5;
  531.     Score=NULL;
  532.     SetRast(MyWindow->RPort,0L);
  533.     UpDate_Status(Play_Level,Score,Lives);
  534.     MicroSpeed=(10L-((long)UserSpeed))*SPEED_UP;
  535.     SoundSpeed=0;
  536.     SetPointer(MyWindow,Play_Pointer,1L,1L,-1L,0L);
  537.     Do_Play();
  538.     Sound_Play(2,BIGNUM,0);
  539.     ClearPointer(MyWindow);
  540.     Set_Color_Level(0);
  541.     Request_HighScores(Score);
  542.     ShowWait();
  543.  
  544.     ModifyIDCMP(MyWindow,tmpIDCMP);
  545.  
  546.     OnMenu (MyWindow,SHIFTMENU(1)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
  547.     OnMenu (MyWindow,SHIFTMENU(0)|SHIFTITEM(NOITEM)|SHIFTSUB(NOSUB) );
  548. }
  549.