home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / DESQVIEW / API_EXAM.ZIP / SNAKES.C < prev    next >
Text File  |  1988-04-28  |  10KB  |  331 lines

  1. /****************************************************************
  2. *
  3. *  Name:          SNAKES
  4. *
  5. *  Function:      display multiple "snakes" each controlled by a
  6. *                 separate task.
  7. *
  8. *  Shows how to:  1. create and terminate subtasks.
  9. *                 2. use mail to send initial data to a new task.
  10. *                 3. use a semaphore to control access to a 
  11. *                    resource, in this case the window.
  12. *                 4. read and write the window contents.
  13. *
  14. ****************************************************************/
  15.  
  16. #include <stdio.h>
  17. #include "dvapi.h"
  18.  
  19. /* minimum API version required */
  20. #define required 0x201
  21.  
  22. /* number of tasks supported and the stack size for each */
  23. #define ntasks 8
  24. #define stksize 256
  25.  
  26. /* object handles */
  27. ulong win,kbd,sema,menuwin,menukbd,taskhan[ntasks];
  28.  
  29. /* step sizes in each direction {up,right,down,left} */
  30. int   row_offsets[4] = {-1,0,1,0};
  31. int   col_offsets[4] = {0,2,0,-2};
  32.  
  33. /* variables used to read menu data */
  34. char *kbuf,field;
  35. int   klng;
  36.  
  37. /* other variables */
  38. int   next = 0;         /* next task number available */
  39. int   locked = 0;       /* TRUE if snakes are suspended */
  40. int   version;          /* actual API version */
  41.  
  42. /* this string defines the menu contents */
  43. char menu1[] = "\
  44.  Create a new snake     C \
  45.  Kill a snake           K \
  46.  Bury dead snakes       B \
  47.  Start/Stop all snakes  S \
  48.  Exit                   E ";
  49.  
  50. /* this string defines the menu's field table */
  51. char ftab1[] = {ftab(5,FTH_KEYSELECT+FTH_MODIFIED,0,0,9,1),
  52.                      0,0,0,25,FTE_SELECT,'C',1,0,
  53.                      1,0,1,25,FTE_SELECT,'K',1,0,
  54.                      2,0,2,25,FTE_SELECT,'B',1,0,
  55.                      3,0,3,25,FTE_SELECT,'S',1,0,
  56.                      4,0,4,25,FTE_SELECT,'E',1,0,
  57.                      };
  58.  
  59. /* subtask entry point - defined here to allow forward reference */
  60. int snake();
  61.  
  62. /**********************************************************************
  63. *  main  -  check for DESQview present and enable required extensions.
  64. ***********************************************************************/
  65.  
  66. main () {
  67.   /* initialize C interfaces and get API version number */
  68.   version = api_init();
  69.  
  70.   /* if DESQview is not running or version is too low, display a message */ 
  71.   if (version < required) {
  72.     printf ("This program requires DESQview version %d.02%d or later.\n",
  73.              required/256,required%256);
  74.     }
  75.  
  76.   /* tell DESQview what extensions to enable and start application */
  77.   else {
  78.     api_level (required);
  79.     program_body();
  80.     }
  81.  
  82.   /* disable C interfaces and return from program */
  83.   api_exit();
  84.   }
  85.  
  86.  
  87. /**********************************************************************
  88. *  program_body  -  create and display menu window.  Loop processing
  89. *                   menu input.
  90. ***********************************************************************/
  91.  
  92. program_body () {
  93.   /* reserve stack space for subtasks on primary stack so that stack
  94.      bounds checking still works.  Define other local variables. */
  95.   char   stacks[ntasks][stksize];
  96.   int i,k,done;
  97.  
  98.   /* get default object handles.  Allocate semaphore (mailbox). */
  99.   win = win_me();
  100.   kbd = key_me();
  101.   sema = mal_new();
  102.  
  103.   /* set logical attributes and make task window full screen */
  104.   win_logattr (win,1);
  105.   win_attr (win,1);
  106.   win_erase (win);
  107.   win_origin (win,0,0);
  108.   win_move (win,0,0);
  109.   win_resize (win,25,80);
  110.   win_redraw (win);
  111.  
  112.   /* allocate window and keyboard objects for menu */
  113.   menuwin = win_new ("Snakes",6,5,26);
  114.   menukbd = key_new();
  115.   key_open  (menukbd,menuwin);
  116.   key_addto (menukbd,KBF_FIELD);
  117.  
  118.   /* write contents and field table to menu.  Make topmost in application. */
  119.   win_swrite (menuwin,menu1);
  120.   win_stream (menuwin,ftab1);
  121.   win_move (menuwin,1,53);
  122.   win_unhide (menuwin);
  123.   win_top (menuwin);
  124.  
  125.   /* move mouse to first menu field */
  126.   fld_point (win,1,0,0);
  127.  
  128.   /* loop until done becomes TRUE */
  129.   done = 0;
  130.   while (!done) {
  131.  
  132.     /* wait for menu selection, determine field #, reset to deselected */
  133.     key_read (menukbd,&kbuf,&klng);
  134.     field = *kbuf;
  135.     fld_reset (menuwin);
  136.  
  137.     /* lockout access to screen for all snake tasks */
  138.     mal_lock (sema);
  139.  
  140.     /* dispatch based on selected field number */
  141.     switch (field) {
  142.  
  143.       case 1:   /* Create new snake -  beep if no more snakes allowed */
  144.                 if (next == ntasks)
  145.                   api_sound (2000,5);
  146.                 else {
  147.  
  148.                 /* create a new task to run the "snake" function. */
  149.                 taskhan[next] = tsk_new (snake,stacks[next],stksize,NULL,0,0,0);
  150.  
  151.                 /* tell task what attribute to use by sending a NULL message
  152.                    with the attribute as its status code. */
  153.                 mal_subfrom (mal_of(taskhan[next]),NULL,0,next+1);
  154.  
  155.                 /* bump task count */
  156.                 next += 1;
  157.                 }
  158.                 break;
  159.  
  160.       case 2:   /* Kill a snake -  beep if there are no more snakes to kill */
  161.                 if (next == 0)
  162.                   api_sound (2000,5);
  163.                 else {
  164.  
  165.                 /* decrement task count and kill most recent task */
  166.                   next -= 1;
  167.                   tsk_free (taskhan[next]);
  168.                   }
  169.                 break;
  170.  
  171.       case 3:   /* Bury dead snakes -  erase window to clear all snakes.  
  172.                    Live ones redraw themselves. */
  173.                 win_attr (win,1);
  174.                 win_erase (win);
  175.                 break;
  176.  
  177.       case 4:   /* Stop/Start snakes -  stop snakes by over-locking the 
  178.                    semaphore.  Unlock to start. */ 
  179.                 (locked) ? mal_unlock(sema) : mal_lock(sema);
  180.                 locked = !locked;
  181.                 break;
  182.  
  183.       case 5:   /* Exit - set the "done" flag */ 
  184.                 done = 1;
  185.                 break;
  186.       }
  187.  
  188.     /* unlock snake tasks and loop until "done" */
  189.     mal_unlock (sema);
  190.     }
  191.  
  192.   /* stop all snakes and free their tasks */
  193.   mal_lock (sema);
  194.   for (i=0; i<next; i++) {
  195.     tsk_free (taskhan[i]);
  196.     }
  197.  
  198.   /* free allocated objects */
  199.   mal_free (sema); 
  200.   key_free (menukbd);
  201.   win_free (menuwin);
  202.  
  203.   /* change to physical attributes in case exiting to DOS */
  204.   win_logattr (win,0);
  205.   win_attr (win,7);
  206.   win_erase (win);
  207.   } 
  208.  
  209.  
  210. /**********************************************************************
  211. *  snake  -  continuously move a single snake.
  212. ***********************************************************************/
  213.  
  214. snake () {
  215.   /* all data must be dynamic */
  216.   int row[16],col[16],head_row,head_col,old_row,old_col,i,atr,mallng;
  217.   char *malptr;
  218.  
  219.   /* wait for parent to send attribute to be used */
  220.   atr = mal_read (mal_me(),&malptr,&mallng);
  221.  
  222.   /* initialize array used to log position of each segment of snake */
  223.   for (i=0; i<16; i++) row[i] = -1;
  224.  
  225.   /* set snake start position.  Loop forever moving the snake. */
  226.   head_row = 12;
  227.   head_col = 40;
  228.   while (1) {
  229.  
  230.     /* loop for each segment of snake */
  231.     for (i=0; i<16; i++) {
  232.  
  233.       /* remember head position and compute a new position */
  234.       old_row = head_row;
  235.       old_col = head_col;
  236.       find_new_head (&head_row,&head_col);
  237.  
  238.       /* acquire exclusive access to window and clear tail segment */
  239.       mal_lock (sema);
  240.       if (row[i] != -1) 
  241.         write_segment (row[i],col[i],' ',1);
  242.  
  243.       /* if new head position is occupied, don't move head */
  244.       if (position_occupied(head_row,head_col)) {
  245.         head_row = old_row;
  246.         head_col = old_col;
  247.         }
  248.  
  249.       /* write new head segment and relinquish access to window */
  250.       write_segment (head_row,head_col,0xB2,atr);
  251.       mal_unlock (sema);
  252.  
  253.       /* log new head position in array */
  254.       row[i] = head_row;
  255.       col[i] = head_col;
  256.       }
  257.     }
  258.   }
  259.  
  260.  
  261. /**********************************************************************
  262. *  find_new_head  -  get new head position 
  263. ***********************************************************************/
  264.  
  265. find_new_head (row,col) int *row,*col; {
  266.   int dir,nrow,ncol;
  267.  
  268.   /* use random # to lookup horizontal and vertical steps */
  269.   do {
  270.     dir = rand() & 3;
  271.     nrow = *row + row_offsets[dir];
  272.     ncol = *col + col_offsets[dir];
  273.     }
  274.  
  275.   /* loop if new position is outside window */
  276.   while ((nrow < 0) || (nrow > 24) ||
  277.          (ncol < 0) || (ncol > 78));
  278.  
  279.   /* return new position */
  280.   *row = nrow;
  281.   *col = ncol;
  282.   }
  283.  
  284.  
  285. /**********************************************************************
  286. *  position_occupied  -  return TRUE if there is a char at given position
  287. ***********************************************************************/
  288.  
  289. int position_occupied (row,col) int row,col; {
  290.   char *readptr;
  291.   int readlng;
  292.  
  293.   /* set cursor to position and read a single character */
  294.   win_cursor (win,row,col);
  295.   win_nread (win,1,&readptr,&readlng);
  296.  
  297.   /* return TRUE if it isn't a space */
  298.   return (!(*readptr == ' '));
  299.   }
  300.  
  301.  
  302. /**********************************************************************
  303. *  write_segment  -  write character twice at given position with 
  304. *                    given attribute.
  305. ***********************************************************************/
  306.  
  307. write_segment (row,col,chr,atr) int row,col,chr,atr; {
  308.   win_cursor (win,row,col);
  309.   win_attr (win,atr);
  310.   win_repchar (win,2,chr);
  311.   }
  312.  
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.