AllBASIC Forum

BASIC Developer & Support Resources => Open Forum => Topic started by: John on June 06, 2015, 07:49:02 PM

Title: pacman4console
Post by: John on June 06, 2015, 07:49:02 PM
Pac-Man Trivia

And to close out our anniversary celebrations for Pac-Man, here are a few pieces of trivia less commonly known about our beloved major sector-shaped video game character. Have we missed an interesting factoid? Tell us in the comments, below!

github source repository (https://github.com/alexdantas/pacman4console.debian/tree/debian)

Title: Re: pacman4console
Post by: John on June 12, 2015, 12:42:21 AM
I started on a Script BASIC port of pacman4console as a test / example script for the ncurses extension module.

I'll post something when it works.

It would be great to see a graphics version of this in maybe SDL.
Title: Re: pacman4console
Post by: John on June 12, 2015, 04:02:22 PM
I was making good progress with the pacman4console conversion to Script BASIC until I started testing the curses extension module. Biggest problem I've found so far is whoever wrote it didn't remember the functions returns.

Since Script BASIC (scriba) is console interpreter, complete curses support would probably be a good idea. It seriously needs an updated API approach. (C BASIC)
Title: Re: pacman4console
Post by: John on June 12, 2015, 11:39:32 PM
The cursses extension module needs a rewrite. It used early Script BASIC API methods and shortcuts that are causing segmentation faults running under 64 bit with the current ncurses library. I don't have time to rewrite it and would welcome anyone willing to take on that project.

I'm going to use my ANSI include I used with Android Linux as it doesn't have a native ncurses library that I'm aware of. This should make the game more portable among OS platforms.

Update:

I thought the ANSI include direction was going to work out for the PacMan game but I can't find a way in core Script BASIC to do keyboard input without echoing to the screen.  :o  I'm back to ncurses and rewriting/updating the extension module using C BASIC as a wrapper this time. (new SB standard)

Title: Script BASIC ncurses ext. module
Post by: John on June 14, 2015, 03:12:35 AM
I compiled from source the new ncurses 6.0 release. The library includes Form support and a few other extensions beside the core ncurses features. Attached is a demo of using forms. The worm demo was cool for a terminal application.

Code: C
  1. /****************************************************************************
  2.  * Copyright (c) 1998-2012,2013 Free Software Foundation, Inc.              *
  3.  *                                                                          *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  5.  * copy of this software and associated documentation files (the            *
  6.  * "Software"), to deal in the Software without restriction, including      *
  7.  * without limitation the rights to use, copy, modify, merge, publish,      *
  8.  * distribute, distribute with modifications, sublicense, and/or sell       *
  9.  * copies of the Software, and to permit persons to whom the Software is    *
  10.  * furnished to do so, subject to the following conditions:                 *
  11.  *                                                                          *
  12.  * The above copyright notice and this permission notice shall be included  *
  13.  * in all copies or substantial portions of the Software.                   *
  14.  *                                                                          *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  16.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  18.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  21.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  22.  *                                                                          *
  23.  * Except as contained in this notice, the name(s) of the above copyright   *
  24.  * holders shall not be used in advertising or otherwise to promote the     *
  25.  * sale, use or other dealings in this Software without prior written       *
  26.  * authorization.                                                           *
  27.  ****************************************************************************/
  28. /*
  29.  
  30.          @@@        @@@    @@@@@@@@@@     @@@@@@@@@@@    @@@@@@@@@@@@
  31.          @@@        @@@   @@@@@@@@@@@@    @@@@@@@@@@@@   @@@@@@@@@@@@@
  32.          @@@        @@@  @@@@      @@@@   @@@@           @@@@ @@@  @@@@
  33.          @@@   @@   @@@  @@@        @@@   @@@            @@@  @@@   @@@
  34.          @@@  @@@@  @@@  @@@        @@@   @@@            @@@  @@@   @@@
  35.          @@@@ @@@@ @@@@  @@@        @@@   @@@            @@@  @@@   @@@
  36.           @@@@@@@@@@@@   @@@@      @@@@   @@@            @@@  @@@   @@@
  37.            @@@@  @@@@     @@@@@@@@@@@@    @@@            @@@  @@@   @@@
  38.             @@    @@       @@@@@@@@@@     @@@            @@@  @@@   @@@
  39.  
  40.                                  Eric P. Scott
  41.                           Caltech High Energy Physics
  42.                                  October, 1980
  43.  
  44.                 Hacks to turn this into a test frame for cursor movement:
  45.                         Eric S. Raymond <esr@snark.thyrsus.com>
  46.                                 January, 1995
  47.  
  48.                 July 1995 (esr): worms is now in living color! :-)
  49.  
  50. Options:
  51.         -f                      fill screen with copies of 'WORM' at start.
  52.         -l <n>                  set worm length
  53.         -n <n>                  set number of worms
  54.         -t                      make worms leave droppings
  55.         -T <start> <end>        set trace interval
  56.         -S                      set single-stepping during trace interval
  57.         -N                      suppress cursor-movement optimization
  58.  
  59.   This program makes a good torture-test for the ncurses cursor-optimization
  60.   code.  You can use -T to set the worm move interval over which movement
  61.   traces will be dumped.  The program stops and waits for one character of
  62.   input at the beginning and end of the interval.
  63.  
  64.   $Id: worm.c,v 1.65 2013/06/22 20:01:41 tom Exp $
  65. */
  66.  
  67. #include <test.priv.h>
  68.  
  69. #ifdef USE_PTHREADS
  70. #include <pthread.h>
  71. #endif
  72.  
  73. WANT_USE_WINDOW();
  74.  
  75. #define MAX_WORMS       40
  76. #define MAX_LENGTH      1024
  77.  
  78. static chtype flavor[] =
  79. {
  80.     'O', '*', '#', '$', '%', '0', '@',
  81. };
  82. static const int xinc[] =
  83. {
  84.     1, 1, 1, 0, -1, -1, -1, 0
  85. }, yinc[] =
  86. {
  87.     -1, 0, 1, 1, 1, 0, -1, -1
  88. };
  89.  
  90. typedef struct worm {
  91.     int orientation;
  92.     int head;
  93.     int *xpos;
  94.     int *ypos;
  95.     chtype attrs;
  96. #ifdef USE_PTHREADS
  97.     pthread_t thread;
  98. #endif
  99. } WORM;
  100.  
  101. static unsigned long sequence = 0;
  102. static bool quitting = FALSE;
  103.  
  104. static WORM worm[MAX_WORMS];
  105. static int **refs;
  106. static int last_x, last_y;
  107.  
  108. static const char *field;
  109. static int length = 16, number = 3;
  110. static chtype trail = ' ';
  111.  
  112. static unsigned pending;
  113. #ifdef TRACE
  114. static int generation, trace_start, trace_end;
  115. #endif /* TRACE */
  116. /* *INDENT-OFF* */
  117. static const struct options {
  118.     int nopts;
  119.     int opts[3];
  120. } normal[8]={
  121.     { 3, { 7, 0, 1 } },
  122.     { 3, { 0, 1, 2 } },
  123.     { 3, { 1, 2, 3 } },
  124.     { 3, { 2, 3, 4 } },
  125.     { 3, { 3, 4, 5 } },
  126.     { 3, { 4, 5, 6 } },
  127.     { 3, { 5, 6, 7 } },
  128.     { 3, { 6, 7, 0 } }
  129. }, upper[8]={
  130.     { 1, { 1, 0, 0 } },
  131.     { 2, { 1, 2, 0 } },
  132.     { 0, { 0, 0, 0 } },
  133.     { 0, { 0, 0, 0 } },
  134.     { 0, { 0, 0, 0 } },
  135.     { 2, { 4, 5, 0 } },
  136.     { 1, { 5, 0, 0 } },
  137.     { 2, { 1, 5, 0 } }
  138. }, left[8]={
  139.     { 0, { 0, 0, 0 } },
  140.     { 0, { 0, 0, 0 } },
  141.     { 0, { 0, 0, 0 } },
  142.     { 2, { 2, 3, 0 } },
  143.     { 1, { 3, 0, 0 } },
  144.     { 2, { 3, 7, 0 } },
  145.     { 1, { 7, 0, 0 } },
  146.     { 2, { 7, 0, 0 } }
  147. }, right[8]={
  148.     { 1, { 7, 0, 0 } },
  149.     { 2, { 3, 7, 0 } },
  150.     { 1, { 3, 0, 0 } },
  151.     { 2, { 3, 4, 0 } },
  152.     { 0, { 0, 0, 0 } },
  153.     { 0, { 0, 0, 0 } },
  154.     { 0, { 0, 0, 0 } },
  155.     { 2, { 6, 7, 0 } }
  156. }, lower[8]={
  157.     { 0, { 0, 0, 0 } },
  158.     { 2, { 0, 1, 0 } },
  159.     { 1, { 1, 0, 0 } },
  160.     { 2, { 1, 5, 0 } },
  161.     { 1, { 5, 0, 0 } },
  162.     { 2, { 5, 6, 0 } },
  163.     { 0, { 0, 0, 0 } },
  164.     { 0, { 0, 0, 0 } }
  165. }, upleft[8]={
  166.     { 0, { 0, 0, 0 } },
  167.     { 0, { 0, 0, 0 } },
  168.     { 0, { 0, 0, 0 } },
  169.     { 0, { 0, 0, 0 } },
  170.     { 0, { 0, 0, 0 } },
  171.     { 1, { 3, 0, 0 } },
  172.     { 2, { 1, 3, 0 } },
  173.     { 1, { 1, 0, 0 } }
  174. }, upright[8]={
  175.     { 2, { 3, 5, 0 } },
  176.     { 1, { 3, 0, 0 } },
  177.     { 0, { 0, 0, 0 } },
  178.     { 0, { 0, 0, 0 } },
  179.     { 0, { 0, 0, 0 } },
  180.     { 0, { 0, 0, 0 } },
  181.     { 0, { 0, 0, 0 } },
  182.     { 1, { 5, 0, 0 } }
  183. }, lowleft[8]={
  184.     { 3, { 7, 0, 1 } },
  185.     { 0, { 0, 0, 0 } },
  186.     { 0, { 0, 0, 0 } },
  187.     { 1, { 1, 0, 0 } },
  188.     { 2, { 1, 7, 0 } },
  189.     { 1, { 7, 0, 0 } },
  190.     { 0, { 0, 0, 0 } },
  191.     { 0, { 0, 0, 0 } }
  192. }, lowright[8]={
  193.     { 0, { 0, 0, 0 } },
  194.     { 1, { 7, 0, 0 } },
  195.     { 2, { 5, 7, 0 } },
  196.     { 1, { 5, 0, 0 } },
  197.     { 0, { 0, 0, 0 } },
  198.     { 0, { 0, 0, 0 } },
  199.     { 0, { 0, 0, 0 } },
  200.     { 0, { 0, 0, 0 } }
  201. };
  202. /* *INDENT-ON* */
  203.  
  204. static void
  205. failed(const char *s)
  206. {
  207.     perror(s);
  208.     endwin();
  209.     ExitProgram(EXIT_FAILURE);
  210. }
  211.  
  212. static void
  213. cleanup(void)
  214. {
  215.     USING_WINDOW(stdscr, wrefresh);
  216.     curs_set(1);
  217.     endwin();
  218. }
  219.  
  220. static void
  221. onsig(int sig GCC_UNUSED)
  222. {
  223.     cleanup();
  224.     ExitProgram(EXIT_FAILURE);
  225. }
  226.  
  227. static double
  228. ranf(void)
  229. {
  230.     long r = (rand() & 077777);
  231.     return ((double) r / 32768.);
  232. }
  233.  
  234. static int
  235. draw_worm(WINDOW *win, void *data)
  236. {
  237.     WORM *w = (WORM *) data;
  238.     const struct options *op;
  239.     unsigned mask = (unsigned) (~(1 << (w - worm)));
  240.     chtype attrs = w->attrs | ((mask & pending) ? A_REVERSE : 0);
  241.  
  242.     int x;
  243.     int y;
  244.     int h;
  245.  
  246.     bool done = FALSE;
  247.  
  248.     if ((x = w->xpos[h = w->head]) < 0) {
  249.         wmove(win, y = w->ypos[h] = last_y, x = w->xpos[h] = 0);
  250.         waddch(win, attrs);
  251.         refs[y][x]++;
  252.     } else {
  253.         y = w->ypos[h];
  254.     }
  255.  
  256.     if (x > last_x)
  257.         x = last_x;
  258.     if (y > last_y)
  259.         y = last_y;
  260.  
  261.     if (++h == length)
  262.         h = 0;
  263.  
  264.     if (w->xpos[w->head = h] >= 0) {
  265.         int x1, y1;
  266.         x1 = w->xpos[h];
  267.         y1 = w->ypos[h];
  268.         if (y1 < LINES
  269.             && x1 < COLS
  270.             && --refs[y1][x1] == 0) {
  271.             wmove(win, y1, x1);
  272.             waddch(win, trail);
  273.         }
  274.     }
  275.  
  276.     op = &(x == 0
  277.            ? (y == 0
  278.               ? upleft
  279.               : (y == last_y
  280.                  ? lowleft
  281.                  : left))
  282.            : (x == last_x
  283.               ? (y == 0
  284.                  ? upright
  285.                  : (y == last_y
  286.                     ? lowright
  287.                     : right))
  288.               : (y == 0
  289.                  ? upper
  290.                  : (y == last_y
  291.                     ? lower
  292.                     : normal))))[w->orientation];
  293.  
  294.     switch (op->nopts) {
  295.     case 0:
  296.         done = TRUE;
  297.         break;
  298.     case 1:
  299.         w->orientation = op->opts[0];
  300.         break;
  301.     default:
  302.         w->orientation = op->opts[(int) (ranf() * (double) op->nopts)];
  303.         break;
  304.     }
  305.  
  306.     if (!done) {
  307.         x += xinc[w->orientation];
  308.         y += yinc[w->orientation];
  309.         wmove(win, y, x);
  310.  
  311.         if (y < 0)
  312.             y = 0;
  313.         waddch(win, attrs);
  314.  
  315.         w->ypos[h] = y;
  316.         w->xpos[h] = x;
  317.         refs[y][x]++;
  318.     }
  319.  
  320.     return done;
  321. }
  322.  
  323. #ifdef USE_PTHREADS
  324. static bool
  325. quit_worm(int bitnum)
  326. {
  327.     pending |= (1 << bitnum);
  328.     napms(10);                  /* let the other thread(s) have a chance */
  329.     pending &= ~(1 << bitnum);
  330.     return quitting;
  331. }
  332.  
  333. static void *
  334. start_worm(void *arg)
  335. {
  336.     unsigned long compare = 0;
  337.     Trace(("start_worm"));
  338.     while (!quit_worm(((struct worm *) arg) - worm)) {
  339.         while (compare < sequence) {
  340.             ++compare;
  341. #if HAVE_USE_WINDOW
  342.             use_window(stdscr, draw_worm, arg);
  343. #else
  344.             draw_worm(stdscr, arg);
  345. #endif
  346.         }
  347.     }
  348.     Trace(("...start_worm (done)"));
  349.     return NULL;
  350. }
  351. #endif
  352.  
  353. static bool
  354. draw_all_worms(void)
  355. {
  356.     bool done = FALSE;
  357.     int n;
  358.     struct worm *w;
  359.  
  360. #ifdef USE_PTHREADS
  361.     static bool first = TRUE;
  362.     if (first) {
  363.         first = FALSE;
  364.         for (n = 0, w = &worm[0]; n < number; n++, w++) {
  365.             (void) pthread_create(&(w->thread), NULL, start_worm, w);
  366.         }
  367.     }
  368. #else
  369.     for (n = 0, w = &worm[0]; n < number; n++, w++) {
  370.         if (
  371. #if HAVE_USE_WINDOW
  372.                USING_WINDOW2(stdscr, draw_worm, w)
  373. #else
  374.                draw_worm(stdscr, w)
  375. #endif
  376.             )
  377.             done = TRUE;
  378.     }
  379. #endif
  380.     return done;
  381. }
  382.  
  383. static int
  384. get_input(void)
  385. {
  386.     int ch;
  387.     ch = USING_WINDOW(stdscr, wgetch);
  388.     return ch;
  389. }
  390.  
  391. #ifdef KEY_RESIZE
  392. static int
  393. update_refs(WINDOW *win)
  394. {
  395.     int x, y;
  396.  
  397.     (void) win;
  398.     if (last_x != COLS - 1) {
  399.         for (y = 0; y <= last_y; y++) {
  400.             refs[y] = typeRealloc(int, (size_t) COLS, refs[y]);
  401.             if (!refs[y])
  402.                 failed("update_refs");
  403.             for (x = last_x + 1; x < COLS; x++)
  404.                 refs[y][x] = 0;
  405.         }
  406.         last_x = COLS - 1;
  407.     }
  408.     if (last_y != LINES - 1) {
  409.         for (y = LINES; y <= last_y; y++)
  410.             free(refs[y]);
  411.         refs = typeRealloc(int *, (size_t) LINES, refs);
  412.         for (y = last_y + 1; y < LINES; y++) {
  413.             refs[y] = typeMalloc(int, (size_t) COLS);
  414.             if (!refs[y])
  415.                 failed("update_refs");
  416.             for (x = 0; x < COLS; x++)
  417.                 refs[y][x] = 0;
  418.         }
  419.         last_y = LINES - 1;
  420.     }
  421.     return OK;
  422. }
  423. #endif
  424.  
  425. int
  426. main(int argc, char *argv[])
  427. {
  428.     int x, y;
  429.     int n;
  430.     struct worm *w;
  431.     int *ip;
  432.     bool done = FALSE;
  433.     int max_refs;
  434.  
  435.     setlocale(LC_ALL, "");
  436.  
  437.     for (x = 1; x < argc; x++) {
  438.         char *p;
  439.         p = argv[x];
  440.         if (*p == '-')
  441.             p++;
  442.         switch (*p) {
  443.         case 'f':
  444.             field = "WORM";
  445.             break;
  446.         case 'l':
  447.             if (++x == argc)
  448.                 goto usage;
  449.             if ((length = atoi(argv[x])) < 2 || length > MAX_LENGTH) {
  450.                 fprintf(stderr, "%s: Invalid length\n", *argv);
  451.                 ExitProgram(EXIT_FAILURE);
  452.             }
  453.             break;
  454.         case 'n':
  455.             if (++x == argc)
  456.                 goto usage;
  457.             if ((number = atoi(argv[x])) < 1 || number > MAX_WORMS) {
  458.                 fprintf(stderr, "%s: Invalid number of worms\n", *argv);
  459.                 ExitProgram(EXIT_FAILURE);
  460.             }
  461.             break;
  462.         case 't':
  463.             trail = '.';
  464.             break;
  465. #ifdef TRACE
  466.         case 'T':
  467.             trace_start = atoi(argv[++x]);
  468.             trace_end = atoi(argv[++x]);
  469.             break;
  470.         case 'N':
  471.             _nc_optimize_enable ^= OPTIMIZE_ALL;        /* declared by ncurses */
  472.             break;
  473. #endif /* TRACE */
  474.         default:
  475.           usage:
  476.             fprintf(stderr,
  477.                     "usage: %s [-field] [-length #] [-number #] [-trail]\n", *argv);
  478.             ExitProgram(EXIT_FAILURE);
  479.         }
  480.     }
  481.  
  482.     signal(SIGINT, onsig);
  483.     initscr();
  484.     noecho();
  485.     cbreak();
  486.     nonl();
  487.  
  488.     curs_set(0);
  489.  
  490.     last_y = LINES - 1;
  491.     last_x = COLS - 1;
  492.  
  493. #ifdef A_COLOR
  494.     if (has_colors()) {
  495.         int bg = COLOR_BLACK;
  496.         start_color();
  497. #if HAVE_USE_DEFAULT_COLORS
  498.         if (use_default_colors() == OK)
  499.             bg = -1;
  500. #endif
  501.  
  502. #define SET_COLOR(num, fg) \
  503.             init_pair(num+1, (short) fg, (short) bg); \
  504.             flavor[num] |= (chtype) COLOR_PAIR(num+1) | A_BOLD
  505.  
  506.         SET_COLOR(0, COLOR_GREEN);
  507.         SET_COLOR(1, COLOR_RED);
  508.         SET_COLOR(2, COLOR_CYAN);
  509.         SET_COLOR(3, COLOR_WHITE);
  510.         SET_COLOR(4, COLOR_MAGENTA);
  511.         SET_COLOR(5, COLOR_BLUE);
  512.         SET_COLOR(6, COLOR_YELLOW);
  513.     }
  514. #endif /* A_COLOR */
  515.  
  516.     max_refs = LINES;
  517.     refs = typeMalloc(int *, (size_t) max_refs);
  518.     for (y = 0; y < max_refs; y++) {
  519.         refs[y] = typeMalloc(int, (size_t) COLS);
  520.         for (x = 0; x < COLS; x++) {
  521.             refs[y][x] = 0;
  522.         }
  523.     }
  524.  
  525. #ifdef BADCORNER
  526.     /* if addressing the lower right corner doesn't work in your curses */
  527.     refs[last_y][last_x] = 1;
  528. #endif /* BADCORNER */
  529.  
  530.     for (n = number, w = &worm[0]; --n >= 0; w++) {
  531.         w->attrs = flavor[(unsigned) n % SIZEOF(flavor)];
  532.         w->orientation = 0;
  533.         w->head = 0;
  534.  
  535.         if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
  536.             fprintf(stderr, "%s: out of memory\n", *argv);
  537.             ExitProgram(EXIT_FAILURE);
  538.         }
  539.         w->xpos = ip;
  540.         for (x = length; --x >= 0;)
  541.             *ip++ = -1;
  542.         if (!(ip = typeMalloc(int, (size_t) (length + 1)))) {
  543.             fprintf(stderr, "%s: out of memory\n", *argv);
  544.             ExitProgram(EXIT_FAILURE);
  545.         }
  546.         w->ypos = ip;
  547.         for (y = length; --y >= 0;)
  548.             *ip++ = -1;
  549.     }
  550.     if (field) {
  551.         const char *p;
  552.         p = field;
  553.         for (y = last_y; --y >= 0;) {
  554.             for (x = COLS; --x >= 0;) {
  555.                 addch((chtype) (*p++));
  556.                 if (!*p)
  557.                     p = field;
  558.             }
  559.         }
  560.     }
  561.     USING_WINDOW(stdscr, wrefresh);
  562.     nodelay(stdscr, TRUE);
  563.  
  564.     while (!done) {
  565.         int ch;
  566.  
  567.         ++sequence;
  568.         if ((ch = get_input()) > 0) {
  569. #ifdef TRACE
  570.             if (trace_start || trace_end) {
  571.                 if (generation == trace_start) {
  572.                     trace(TRACE_CALLS);
  573.                     get_input();
  574.                 } else if (generation == trace_end) {
  575.                     trace(0);
  576.                     get_input();
  577.                 }
  578.  
  579.                 generation++;
  580.             }
  581. #endif
  582.  
  583. #ifdef KEY_RESIZE
  584.             if (ch == KEY_RESIZE) {
  585.                 USING_WINDOW(stdscr, update_refs);
  586.             }
  587. #endif
  588.  
  589.             /*
  590.              * Make it simple to put this into single-step mode, or resume
  591.              * normal operation -T.Dickey
  592.              */
  593.             if (ch == 'q') {
  594.                 quitting = TRUE;
  595.                 done = TRUE;
  596.                 continue;
  597.             } else if (ch == 's') {
  598.                 nodelay(stdscr, FALSE);
  599.             } else if (ch == ' ') {
  600.                 nodelay(stdscr, TRUE);
  601.             }
  602.         }
  603.  
  604.         done = draw_all_worms();
  605.         napms(10);
  606.         USING_WINDOW(stdscr, wrefresh);
  607.     }
  608.  
  609.     Trace(("Cleanup"));
  610.     cleanup();
  611. #ifdef NO_LEAKS
  612.     for (y = 0; y < max_refs; y++) {
  613.         free(refs[y]);
  614.     }
  615.     free(refs);
  616.     for (n = number, w = &worm[0]; --n >= 0; w++) {
  617.         free(w->xpos);
  618.         free(w->ypos);
  619.     }
  620. #endif
  621. #ifdef USE_PTHREADS
  622.     /*
  623.      * Do this just in case one of the threads did not really exit.
  624.      */
  625.     Trace(("join all threads"));
  626.     for (n = 0; n < number; n++) {
  627.         pthread_join(worm[n].thread, NULL);
  628.     }
  629. #endif
  630.     ExitProgram(EXIT_SUCCESS);
  631. }
  632.  

I'm almost done with the rewrite of the Script BASIC curses extension module.