home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume18 / xmris / part03 < prev    next >
Text File  |  1992-07-16  |  51KB  |  1,762 lines

  1. Newsgroups: comp.sources.x
  2. Path: uunet!usc!sdd.hp.com!mips!msi!dcmartin
  3. From: Nathan Sidwell <nathan@inmos.co.uk>
  4. Subject: v18i024: Xmris - an X video game, Part03/09
  5. Message-ID: <1992Jul16.171724.1709@msi.com>
  6. Originator: dcmartin@fascet
  7. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  8. Organization: Molecular Simulations, Inc.
  9. References: <csx-18i022-xmris@uunet.UU.NET>
  10. Date: Thu, 16 Jul 1992 17:17:24 GMT
  11. Approved: dcmartin@msi.com
  12. Lines: 1748
  13.  
  14. Submitted-by: Nathan Sidwell <nathan@inmos.co.uk>
  15. Posting-number: Volume 18, Issue 24
  16. Archive-name: xmris/part03
  17.  
  18. # this is part.03 (part 3 of a multipart archive)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file create.c continued
  21. #
  22. if test ! -r _shar_seq_.tmp; then
  23.     echo 'Please unpack part 1 first!'
  24.     exit 1
  25. fi
  26. (read Scheck
  27.  if test "$Scheck" != 3; then
  28.     echo Please unpack part "$Scheck" next!
  29.     exit 1
  30.  else
  31.     exit 0
  32.  fi
  33. ) < _shar_seq_.tmp || exit 1
  34. if test ! -f _shar_wnt_.tmp; then
  35.     echo 'x - still skipping create.c'
  36. else
  37. echo 'x - continuing file create.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'create.c' &&
  39. X {-PLAYER_UP2_BALL_X - BALL_WIDTH / 2,  PLAYER_UP2_BALL_Y - BALL_HEIGHT / 2},
  40. X { PLAYER_UP1_BALL_X - BALL_WIDTH / 2, -PLAYER_UP1_BALL_Y - BALL_HEIGHT / 2},
  41. X { PLAYER_UP2_BALL_X - BALL_WIDTH / 2, -PLAYER_UP2_BALL_Y - BALL_HEIGHT / 2},
  42. X {-PLAYER_RIGHT1_BALL_X - BALL_WIDTH / 2, PLAYER_RIGHT1_BALL_Y - BALL_HEIGHT / 2},
  43. X {-PLAYER_RIGHT2_BALL_X - BALL_WIDTH / 2, PLAYER_RIGHT2_BALL_Y - BALL_HEIGHT / 2},
  44. X { PLAYER_RIGHT1_BALL_X - BALL_WIDTH / 2, PLAYER_RIGHT1_BALL_Y - BALL_HEIGHT / 2},
  45. X { PLAYER_RIGHT2_BALL_X - BALL_WIDTH / 2, PLAYER_RIGHT2_BALL_Y - BALL_HEIGHT / 2},
  46. X { PLAYER_UP1_BALL_X - BALL_WIDTH / 2,  PLAYER_UP1_BALL_Y - BALL_HEIGHT / 2},
  47. X { PLAYER_UP2_BALL_X - BALL_WIDTH / 2,  PLAYER_UP2_BALL_Y - BALL_HEIGHT / 2},
  48. X {-PLAYER_UP1_BALL_X - BALL_WIDTH / 2, -PLAYER_UP1_BALL_Y - BALL_HEIGHT / 2},
  49. X {-PLAYER_UP2_BALL_X - BALL_WIDTH / 2, -PLAYER_UP2_BALL_Y - BALL_HEIGHT / 2},
  50. X {-PLAYER_PUSH1_BALL_X - BALL_WIDTH / 2, PLAYER_PUSH1_BALL_Y - BALL_HEIGHT / 2},
  51. X {-PLAYER_PUSH2_BALL_X - BALL_WIDTH / 2, PLAYER_PUSH2_BALL_Y - BALL_HEIGHT / 2},
  52. X { PLAYER_PUSH1_BALL_X - BALL_WIDTH / 2, PLAYER_PUSH1_BALL_Y - BALL_HEIGHT / 2},
  53. X { PLAYER_PUSH2_BALL_X - BALL_WIDTH / 2, PLAYER_PUSH2_BALL_Y - BALL_HEIGHT / 2},
  54. };
  55. /*}}}*/
  56. /*{{{  COORD const ball_throw[8] =*/
  57. COORD const ball_throw[8] =
  58. {
  59. X  {-GAP_WIDTH / 2, -(CELL_HEIGHT + GAP_HEIGHT) / 2},
  60. X  {GAP_WIDTH / 2, (CELL_HEIGHT + GAP_HEIGHT) / 2},
  61. X  {-(CELL_WIDTH + GAP_WIDTH) / 2, GAP_HEIGHT / 2},
  62. X  {(CELL_WIDTH + GAP_WIDTH) / 2, GAP_HEIGHT / 2},
  63. X  {GAP_WIDTH / 2, -(CELL_HEIGHT + GAP_HEIGHT) / 2},
  64. X  {-GAP_WIDTH / 2, (CELL_HEIGHT + GAP_HEIGHT) / 2},
  65. X  {-(CELL_WIDTH + GAP_WIDTH) / 2, GAP_HEIGHT / 2},
  66. X  {(CELL_WIDTH + GAP_WIDTH) / 2, GAP_HEIGHT / 2},
  67. };
  68. /*}}}*/
  69. int const ball_dir[8] = {0, 1, 2, 1, 3, 2, 2, 1};
  70. /*{{{  int const player_dies[8] =*/
  71. int const player_dies[8] =
  72. X  {
  73. X    SPRITE_PLAYER_DEAD + 1,
  74. X    SPRITE_PLAYER + 0,
  75. X    SPRITE_PLAYER + 4,
  76. X    SPRITE_PLAYER + 2,
  77. X    SPRITE_PLAYER + 8,
  78. X    SPRITE_PLAYER + 6,
  79. X    SPRITE_PLAYER + 10,
  80. X    SPRITE_PLAYER_DEAD + 0,
  81. X  };
  82. /*}}}*/
  83. /*{{{  char const *title_text[] =*/
  84. char const *title_text[] =
  85. X  {
  86. X    "(C) 1992 Nathan Sidwell",
  87. #if __STDC__
  88. X    XMRISVERSION " " __DATE__, "",
  89. #else
  90. X    "                           ", /* should be enough space */
  91. #endif
  92. X    "Z - Left", "X - Right", "' - Up", "/ - Down", "Space - Throw",
  93. X    "Or use the mouse", "P - Pause", "Q - Quit",
  94. X    "Press a key or button to start", NULL
  95. X  };
  96. /*}}}*/
  97. #if SQUISH_SCORES != 7
  98. X  #error SQUISH_SCORES != 7
  99. #endif
  100. int const squish_scores[SQUISH_SCORES] = {0, 1000, 2000, 4000, 6000, 8000, 9900};
  101. /*}}}*/
  102. /*{{{  void create_resources(arc, argv)*/
  103. extern void create_resources FUNCARGLIST((argc, argv))
  104. int     argc    FUNCARGSEP
  105. char    **argv  FUNCARGTERM
  106. {
  107. X  display.display = XOpenDisplay(display.name);
  108. X  /*{{{  opened?*/
  109. X  if(!display.display)
  110. X    fatal_error("Cannot open display \"%s\"",
  111. X    display.name ? display.name : "DEFAULT", stderr);
  112. X  /*}}}*/
  113. X  /*{{{  open the display*/
  114. X  {
  115. X    display.screen = DefaultScreen(display.display);
  116. X    display.colormap = DefaultColormap(display.display, display.screen);
  117. X    display.root = DefaultRootWindow(display.display);
  118. X    display.depth = DefaultDepth(display.display, display.screen);
  119. X    display.black = BlackPixel(display.display, display.screen);
  120. X    display.white = WhitePixel(display.display, display.screen);
  121. X    display.xor = display.black ^ display.white; /* for xor context */
  122. X    /*
  123. X     * We want to suspend the game in case the window is iconified.
  124. X     * This is more difficult than it sounds.  On the Sun, iconification
  125. X     * seems to produce an UnmapNotify event -- very nice.  DECwindows,
  126. X     * however, informs the application by generating a PropertyNotify
  127. X     * event on a DEC-specific property -- very nasty.  The atom is
  128. X     * not defined in any of the DECwindows headers, so we will try
  129. X     * to get its value from the server, and use it later.  We are
  130. X     * hoping here that all non-DECwindows servers will return None
  131. X     * for this atom.
  132. X     */
  133. X    display.DEC_icon_atom =
  134. X    XInternAtom(display.display, "DEC_WM_ICON_STATE", True);
  135. X    display.event_mask = ExposureMask | (display.DEC_icon_atom == None ?
  136. X    StructureNotifyMask : PropertyChangeMask);
  137. X  }
  138. X  /*}}}*/
  139. X  /*{{{  reverse video?*/
  140. X  if(flags.reverse)
  141. X    {
  142. X      unsigned long temp;
  143. X    
  144. X      temp = display.black;
  145. X      display.black = display.white;
  146. X      display.white = temp;
  147. X    }
  148. X  /*}}}*/
  149. X  /*{{{  set foreground & background types*/
  150. X  {
  151. X    display.background = display.white == 0 ? COLOUR_ZERO :
  152. X    display.white == (1 << display.depth) - 1 ? COLOUR_ONE :
  153. X    COLOUR_WEIRD;
  154. X    display.foreground = display.black == 0 ? COLOUR_ZERO :
  155. X    display.black == (1 << display.depth) - 1 ? COLOUR_ONE :
  156. X    COLOUR_WEIRD;
  157. X  }
  158. X  /*}}}*/
  159. X  /*{{{  get a font*/
  160. X  {
  161. X    font.font = XLoadFont(display.display, font.name);
  162. X    if(!font.font)
  163. X      fatal_error("Cannot load font \"%s\"", font.name);
  164. X  }
  165. X  /*}}}*/
  166. X  /*{{{  create graphics contexts*/
  167. X  {
  168. X    XGCValues gcv;
  169. X    CONTEXT   *cptr;
  170. X    unsigned  count;
  171. X    
  172. X    gcv.plane_mask = AllPlanes;
  173. X    gcv.font       = font.font;
  174. X    gcv.graphics_exposures = False;
  175. X    gcv.line_width = 1;
  176. X    gcv.line_style = LineSolid;
  177. X    gcv.join_style = JoinMiter;
  178. X    gcv.fill_style = FillSolid;
  179. X    for(cptr = gcsdefine, count = 0; count != GCS; count++, cptr++)
  180. X      {
  181. X    gcv.function = cptr->function;
  182. X    gcv.foreground = *cptr->fgp;
  183. X    gcv.background = *cptr->bgp;
  184. X    GCN(count) = XCreateGC(display.display, display.root, 
  185. X        GCForeground | GCBackground | GCFunction |
  186. X        GCFont | GCGraphicsExposures | GCPlaneMask |
  187. X        GCLineStyle | GCLineWidth | GCJoinStyle | GCFillStyle, &gcv);
  188. X    if(!GCN(count))
  189. X      fatal_error("Cannot create context %d", count);
  190. X      }
  191. X  }
  192. X  /*}}}*/
  193. X  /*{{{  create window*/
  194. X  {
  195. X    XSizeHints hints;
  196. X    XColor colors[2];
  197. X    Pixmap cursor, mask;
  198. X    
  199. X    hints.flags = PSize | PMinSize | PMaxSize;
  200. X    hints.width = WINDOW_WIDTH;
  201. X    hints.height = WINDOW_HEIGHT;
  202. X    hints.min_width = hints.max_width = hints.width;
  203. X    hints.min_height = hints.max_height = hints.height;
  204. X    colors[0].pixel = display.black;
  205. X    colors[1].pixel = display.white;
  206. X    XQueryColors(display.display, display.colormap, colors, 2);
  207. X    display.icon = XCreatePixmapFromBitmapData(display.display,
  208. X    display.root, icons[flags.gender].mask_bits,
  209. X    icons[flags.gender].width, icons[flags.gender].height, 1, 0, 1);
  210. X    if(!display.icon)
  211. X      fatal_error("Cannot create window icon");
  212. X    cursor = mask = 0;
  213. X    cursor = XCreatePixmapFromBitmapData(display.display,
  214. X    display.root, cursor_bits,
  215. X    cursor_width, cursor_height, 1, 0, 1);
  216. X    mask = XCreatePixmapFromBitmapData(display.display,
  217. X    display.root, cursorm_bits,
  218. X    cursorm_width, cursorm_height, 1, 0, 1);
  219. X    if(cursor && mask)
  220. X      display.cursor = XCreatePixmapCursor(display.display,
  221. X      cursor, mask, &colors[0], &colors[1],
  222. X      cursor_x_hot, cursor_y_hot);
  223. X    if(cursor)
  224. X      XFreePixmap(display.display, cursor);
  225. X    if(mask)
  226. X      XFreePixmap(display.display, mask);
  227. X    if(!display.cursor)
  228. X      fatal_error("Cannot create cursor icon");
  229. X    display.window = XCreateSimpleWindow(display.display, display.root,
  230. X    0, 0, hints.width, hints.height, 1, display.black, display.white);
  231. X    if(!display.window)
  232. X      fatal_error("Cannot create window");
  233. X    XSetStandardProperties(display.display, display.window,
  234. X    game_name, game_name, display.icon, argv, argc, &hints);
  235. X    XDefineCursor(display.display, display.window, display.cursor);
  236. X  }
  237. X  /*}}}*/
  238. X  display.back = XCreatePixmap(display.display, display.root,
  239. X      WINDOW_WIDTH, WINDOW_HEIGHT, display.depth);
  240. X  display.copy = XCreatePixmap(display.display, display.root,
  241. X      WINDOW_WIDTH, WINDOW_HEIGHT, display.depth);
  242. X  if(!display.back || !display.copy)
  243. X    fatal_error("Cannot create window copies");
  244. X  /*{{{  are we she?*/
  245. X  if(flags.gender)
  246. X    {
  247. X      memcpy(&sprites[SPRITE_MRIS + 1], &sprites[SPRITE_MRIS + 3],
  248. X      sizeof(SPRITE));
  249. X      memcpy(&sprites[SPRITE_MRIS + 5], &sprites[SPRITE_MRIS + 7],
  250. X      sizeof(SPRITE));
  251. X      memcpy(&sprites[SPRITE_MRIS + 3],  &spritet[0], sizeof(SPRITE));
  252. X      memcpy(&sprites[SPRITE_MRIS + 7],  &spritet[1], sizeof(SPRITE));
  253. X    }
  254. X  /*}}}*/
  255. X  /*{{{  create sprites*/
  256. X  {
  257. X    unsigned  i;
  258. X    SPRITE    *sptr;
  259. X    
  260. X    /*{{{  generate all the ones from bitmaps*/
  261. X    for(i = 0, sptr = sprites; i != SPRITES; i++, sptr++)
  262. X      {
  263. X    /* check that its the size we expected */
  264. X    assert((!sptr->expected.x || sptr->expected.x == sptr->width) &&
  265. X        (!sptr->expected.y || sptr->expected.y == sptr->height));
  266. X    if(sptr->mask_bits || sptr->image_bits)
  267. X      {
  268. X        assert(sptr->width && sptr->height);
  269. X        if(sptr->image_bits)
  270. X          sptr->image = XCreatePixmapFromBitmapData(display.display,
  271. X          display.root, sptr->image_bits,
  272. X          sptr->width, sptr->height,
  273. X          display.black, display.white, display.depth);
  274. X        else
  275. X          {
  276. X        sptr->image = XCreatePixmap(display.display, display.root,
  277. X            sptr->width, sptr->height, display.depth);
  278. X        if(sptr->image)
  279. X          XFillRectangle(display.display, sptr->image, GCN(GC_CLEAR),
  280. X              0, 0, sptr->width, sptr->height);
  281. X          }
  282. X        if(sptr->mask_bits && sptr->image)
  283. X          {
  284. X        sptr->mask = XCreatePixmapFromBitmapData(display.display,
  285. X            display.root, sptr->mask_bits, sptr->width, sptr->height,
  286. X            ((unsigned long)1 << display.depth) - (unsigned long)1,
  287. X            (unsigned long)0, display.depth);
  288. X        if(sptr->mask)
  289. X          XCopyArea(display.display, sptr->mask, sptr->image, GCN(GC_AND),
  290. X              0, 0, sptr->width, sptr->height, 0, 0);
  291. X          }
  292. X        if((!sptr->mask && sptr->mask_bits) || !sptr->image)
  293. X          fatal_error("Cannot create sprite %d", i);
  294. X      }
  295. X      }
  296. X    /*}}}*/
  297. X    /*{{{  do the ball*/
  298. X    {
  299. X      sptr = &sprites[SPRITE_BALL];
  300. X      ball_xor = XCreatePixmap(display.display, display.window,
  301. X      BALL_WIDTH, BALL_HEIGHT, display.depth);
  302. X      if(!ball_xor)
  303. X    fatal_error("Cannot create ball sprite");
  304. X      XFillRectangle(display.display, ball_xor, GCN(GC_MASK),
  305. X      0, 0, BALL_WIDTH, BALL_HEIGHT);
  306. X      XFillRectangle(display.display, ball_xor, GCN(GC_BALL),
  307. X      0, 0, BALL_WIDTH, BALL_HEIGHT);
  308. X      XCopyArea(display.display, sptr->mask, ball_xor, GCN(GC_AND),
  309. X      0, 0, BALL_WIDTH, BALL_HEIGHT, 0, 0);
  310. X    }
  311. X    /*}}}*/
  312. X    /*{{{  now do the copies*/
  313. X    for(sptr = sprites, i = SPRITES; i--; sptr++)
  314. X      if(!sptr->copy)
  315. X    {
  316. X      /* Sun's assert macro is broken, so I have to
  317. X       * put it in a scope */
  318. X      assert(sptr->mask_bits || sptr->image_bits);
  319. X    }
  320. X      else
  321. X    {
  322. X      SPRITE    *optr;
  323. X          
  324. X      optr = &sprites[sptr->copy];
  325. X      assert(optr->width && optr->height);
  326. X      sptr->width = optr->width;
  327. X      sptr->height = optr->height;
  328. X      switch(sptr->reflect)
  329. X      {
  330. X        /*{{{  case 0: (no reflections)*/
  331. X        case 0:
  332. X          sptr->mask = optr->mask;
  333. X          sptr->image = optr->image;
  334. X          break;
  335. X        /*}}}*/
  336. X        /*{{{  case 1: (vertical axis)*/
  337. X        case 1:
  338. X        {
  339. X          int       i;
  340. X                          
  341. X          sptr->mask = XCreatePixmap(display.display, display.root,
  342. X          sptr->width, sptr->height, display.depth);
  343. X          sptr->image = XCreatePixmap(display.display, display.root,
  344. X          sptr->width, sptr->height, display.depth);
  345. X          if(sptr->image && sptr->mask)
  346. X        for(i = sptr->width; i--;)
  347. X          {
  348. X            XCopyArea(display.display, optr->mask, sptr->mask,
  349. X            GCN(GC_COPY),
  350. X            i, 0, 1, sptr->height, sptr->width - i - 1, 0);
  351. X            XCopyArea(display.display, optr->image, sptr->image,
  352. X            GCN(GC_COPY),
  353. X            i, 0, 1, sptr->height, sptr->width - i - 1, 0);
  354. X          }
  355. X          break;
  356. X        }
  357. X        /*}}}*/
  358. X        /*{{{  case 2: (horizontal axis)*/
  359. X        case 2:
  360. X        {
  361. X          int       i;
  362. X                          
  363. X          sptr->mask = XCreatePixmap(display.display, display.root,
  364. X          sptr->width, sptr->height, display.depth);
  365. X          sptr->image = XCreatePixmap(display.display, display.root,
  366. X          sptr->width, sptr->height, display.depth);
  367. X          if(sptr->mask && sptr->image)
  368. X        for(i = sptr->width; i--;)
  369. X          {
  370. X            XCopyArea(display.display, optr->mask, sptr->mask,
  371. X            GCN(GC_COPY),
  372. X            0, i, sptr->width, 1, 0, sptr->height - i - 1);
  373. X            XCopyArea(display.display, optr->image, sptr->image,
  374. X            GCN(GC_COPY),
  375. X            0, i, sptr->width, 1, 0, sptr->height - i - 1);
  376. X          }
  377. X          break;
  378. X        }
  379. X        /*}}}*/
  380. X        /*{{{  default*/
  381. X        default:
  382. X          assert(0);
  383. X        /*}}}*/
  384. X      }
  385. X      if(!sptr->image || !sptr->mask)
  386. X        fatal_error("Cannot generate sprite %d", SPRITES - 1 - i);
  387. X    }
  388. X    /*}}}*/
  389. X  }
  390. X  /*}}}*/
  391. X  /*{{{  check ball hold is ok*/
  392. X  {
  393. X    unsigned  i;
  394. X    
  395. X    for(i = sizeof(ball_hold) / sizeof(COORD); i--;)
  396. X      assert(ball_hold[i].x + CELL_WIDTH / 2 >= 0 &&
  397. X      ball_hold[i].x + CELL_WIDTH / 2 <= CELL_WIDTH - BALL_WIDTH / 2 && 
  398. X      ball_hold[i].y + CELL_HEIGHT / 2 >= 0 &&
  399. X      ball_hold[i].y + CELL_HEIGHT / 2 <= CELL_HEIGHT - BALL_HEIGHT / 2);
  400. X  }
  401. X  /*}}}*/
  402. X  /*{{{  create score pixmaps*/
  403. X  {
  404. X    unsigned  i;
  405. X    
  406. X    for(i = BOARD_SCORES; i--;)
  407. X      {
  408. X    update.score.list[i].image = XCreatePixmap(display.display,
  409. X        display.root, DIGIT_WIDTH * 4, DIGIT_HEIGHT, display.depth);
  410. X    update.score.list[i].mask = XCreatePixmap(display.display,
  411. X        display.root, DIGIT_WIDTH * 4, DIGIT_HEIGHT, display.depth);
  412. X    if(!update.score.list[i].image || !update.score.list[i].mask)
  413. X      fatal_error("Cannot create score pixmap");
  414. X      }
  415. X  }
  416. X  /*}}}*/
  417. X  return;
  418. }
  419. /*}}}*/
  420. /*{{{  void create_xtra_monster(index)*/
  421. extern void create_xtra_monster FUNCARGLIST((index))
  422. int   index FUNCARGTERM
  423. {
  424. X  SPRITE    *dptr;
  425. X  SPRITE    *sptr;
  426. X  SPRITE    *lptr;
  427. X  unsigned  i;
  428. X  
  429. X  sptr = &sprites[SPRITE_XTRA];
  430. X  lptr = &sprites[SPRITE_EXTRA];
  431. X  for(dptr = &sprites[SPRITE_XTRA], sptr = &sprites[SPRITE_XTRA_SOURCE],
  432. X      i = MONSTER_IMAGES; i--; dptr++, sptr++)
  433. X    {
  434. X      XCopyArea(display.display, sptr->image, dptr->image, GCN(GC_COPY),
  435. X      0, 0, CELL_WIDTH, CELL_HEIGHT, 0, 0);
  436. X      XCopyArea(display.display, lptr->mask, dptr->image, GCN(GC_MASK),
  437. X      index * (CELL_WIDTH / 2), 0, CELL_WIDTH / 2, CELL_HEIGHT / 2,
  438. X      XTRA_LETTER_X, XTRA_LETTER_Y);
  439. X      XCopyArea(display.display, lptr[!(extra.got & 1 << index)].image,
  440. X      dptr->image, GCN(GC_OR),
  441. X      index * (CELL_WIDTH / 2), 0, CELL_WIDTH / 2, CELL_HEIGHT / 2,
  442. X      XTRA_LETTER_X, XTRA_LETTER_Y);
  443. X    }
  444. X  return;
  445. }
  446. /*}}}*/
  447. /*{{{  void draw_extra_letter(index)*/
  448. extern void draw_extra_letter FUNCARGLIST((index))
  449. int     index  FUNCARGTERM
  450. {
  451. X  SPRITE    *lptr;
  452. X  int       x;
  453. X  
  454. X  lptr = &sprites[SPRITE_EXTRA];
  455. X  x = XTRA_X + index * XTRA_SPACING;
  456. X  XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  457. X      x, XTRA_Y, CELL_WIDTH, CELL_HEIGHT);
  458. X  XCopyArea(display.display, lptr->mask,
  459. X      display.back, GCN(GC_MASK), index * (CELL_WIDTH / 2), 0,
  460. X      CELL_WIDTH / 2, CELL_HEIGHT / 2,
  461. X      x + XTRA_LETTER_X, XTRA_Y + XTRA_LETTER_Y);
  462. X  XCopyArea(display.display, lptr[!(extra.got & 1 << index)].image,
  463. X      display.back, GCN(GC_OR), index * (CELL_WIDTH / 2), 0,
  464. X      CELL_WIDTH / 2, CELL_HEIGHT / 2,
  465. X      x + XTRA_LETTER_X, XTRA_Y + XTRA_LETTER_Y);
  466. X  add_background(x, XTRA_Y, CELL_WIDTH, CELL_HEIGHT);
  467. X  return;
  468. }
  469. /*}}}*/
  470. /*{{{  void release_resources()*/
  471. extern void release_resources FUNCARGVOID
  472. /*
  473. X * frees all the resources we have allocated by create_resources
  474. X */
  475. {
  476. X  unsigned  i;
  477. X  SPRITE    *sptr;
  478. X
  479. X  if(display.window)
  480. X    {
  481. X      XUnmapWindow(display.display, display.window);
  482. X      XUndefineCursor(display.display, display.window);
  483. X      XDestroyWindow(display.display, display.window);
  484. X    }
  485. X  if(font.font)
  486. X    XUnloadFont(display.display, font.font);
  487. X  if(display.cursor)
  488. X    XFreeCursor(display.display, display.cursor);
  489. X  if(display.copy)
  490. X    XFreePixmap(display.display, display.copy);
  491. X  if(display.back)
  492. X    XFreePixmap(display.display, display.back);
  493. X  if(display.icon)
  494. X    XFreePixmap(display.display, display.icon);
  495. X  /*{{{  free gcs*/
  496. X  {
  497. X    GC        *gcptr;
  498. X    unsigned  count;
  499. X    
  500. X    for(gcptr = gcs, count = GCS; count--; gcptr++)
  501. X      if(*gcptr)
  502. X    {
  503. X      XFreeGC(display.display, *gcptr);
  504. X      *gcptr = 0;
  505. X    }
  506. X  }
  507. X  /*}}}*/
  508. X  for(i = SPRITES, sptr = sprites; i--; sptr++)
  509. X    {
  510. X      if(!sptr->copy || sptr->reflect)
  511. X    {
  512. X      if(sptr->image)
  513. X        XFreePixmap(display.display, sptr->image);
  514. X      if(sptr->mask)
  515. X        XFreePixmap(display.display, sptr->mask);
  516. X    }
  517. X    }
  518. X  for(i = BOARD_SCORES; i--;)
  519. X    {
  520. X      if(update.score.list[i].image)
  521. X    XFreePixmap(display.display, update.score.list[i].image);
  522. X      if(update.score.list[i].mask)
  523. X    XFreePixmap(display.display, update.score.list[i].mask);
  524. X    }
  525. X  if(display.display)
  526. X    {
  527. X      XFlush(display.display);
  528. X      XCloseDisplay(display.display);
  529. X    }
  530. X  return;
  531. }
  532. /*}}}*/
  533. SHAR_EOF
  534. echo 'File create.c is complete' &&
  535. chmod 0644 create.c ||
  536. echo 'restore of create.c failed'
  537. Wc_c="`wc -c < 'create.c'`"
  538. test 37076 -eq "$Wc_c" ||
  539.     echo 'create.c: original size 37076, current size' "$Wc_c"
  540. rm -f _shar_wnt_.tmp
  541. fi
  542. # ============= demo.c ==============
  543. if test -f 'demo.c' -a X"$1" != X"-c"; then
  544.     echo 'x - skipping demo.c (File already exists)'
  545.     rm -f _shar_wnt_.tmp
  546. else
  547. > _shar_wnt_.tmp
  548. echo 'x - extracting demo.c (Text)'
  549. sed 's/^X//' << 'SHAR_EOF' > 'demo.c' &&
  550. /*{{{  (C) 1992 Nathan Sidwell*/
  551. /*****************************************************************************
  552. X            X M R I S V1.01
  553. X            ---------------
  554. X            (C) 1992 Nathan Sidwell
  555. X
  556. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  557. is in the public domain. Permission is granted to distribute and compile
  558. verbatim copies of this software for non-commercial, non-profit use,
  559. without fee. The software may be modified, provided that both the above copyright
  560. notice and this permission notice appear.
  561. X
  562. No guarantee is given as to the robustness or suitability of this
  563. software for your computer.
  564. X
  565. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  566. *****************************************************************************/
  567. /*}}}*/
  568. #include "xmris.h"
  569. /*{{{  prototypes*/
  570. static int demo_board PROTOARGLIST((void));
  571. static int demo_keys PROTOARGLIST((void));
  572. static int move_demo PROTOARGLIST((void));
  573. static void move_mris PROTOARGLIST((void));
  574. /*}}}*/
  575. /*{{{  int demo_board()*/
  576. static int demo_board FUNCARGVOID
  577. {
  578. X  unsigned  den;
  579. X  unsigned  count;
  580. X  unsigned  quit;
  581. X
  582. X  quit = 0;
  583. X  player.screen = random() % 10;
  584. X  extra.select = random() % 5;
  585. X  extra.got = random() & 0x1F;
  586. X  create_xtra_monster(extra.select);
  587. X  new_board();
  588. X  zoom_board();
  589. X  draw_center(SPRITE_DEN);
  590. X  monster.monsters = 0;
  591. X  spawn_monster(4, 2, 2, PLAYER_START_X, PLAYER_START_Y, 0, 0);
  592. X  monster.list[0].stop = 1;
  593. X  monster.den = 0;
  594. X  player.ball.state = 0;
  595. X  player.ball.count = 8;
  596. X  player.old_ball.state = 0;
  597. X  /*{{{  plonk on M R I S*/
  598. X  for(count = 4; count--;)
  599. X    {
  600. X      unsigned  x, y;
  601. X      unsigned  j;
  602. X      CELL      *cptr;
  603. X      
  604. X      do
  605. X    {
  606. X      do
  607. X        j = random();
  608. X      while(j >= CELLS_ACROSS * CELLS_DOWN);
  609. X      x = j % CELLS_ACROSS;
  610. X      y = j / CELLS_ACROSS;
  611. X      cptr = BOARDCELL(x, y);
  612. X    }
  613. X      while(!cptr->visit);
  614. X      spawn_monster(SPRITE_MRIS + count + (random() & 4), 0, 0, x, y, 0, 0);
  615. X    }
  616. X  /*}}}*/
  617. X  refresh_window();
  618. X  count = DISPLAY_HOLD;
  619. X  den = 4;
  620. X  timer_start(FRAME_RATE);
  621. X  while(count)
  622. X    {
  623. X      quit = process_xevents(0);
  624. X      if(quit)
  625. X    {
  626. X      player.button = 1;
  627. X      break;
  628. X    }
  629. X      /*{{{  calc distances?*/
  630. X      if(den != monster.den)
  631. X    {
  632. X      den = monster.den;
  633. X      monster.list[0].cell.y = 0;
  634. X      monster.list[0].cell.x = 4 + den;
  635. X      calc_distances();
  636. X      monster.list[0].cell.y = PLAYER_START_Y;
  637. X      monster.list[0].cell.x = PLAYER_START_X;
  638. X    }
  639. X      /*}}}*/
  640. X      move_mris();
  641. X      if(monster.den == 4)
  642. X    count--;
  643. X      if(player.button)
  644. X    count = 0;
  645. X      show_updates();
  646. X    timer_wait();
  647. X      }
  648. X  timer_stop();
  649. X  return quit;
  650. }
  651. /*}}}*/
  652. /*{{{  int demo_keys()*/
  653. static int demo_keys FUNCARGVOID
  654. {
  655. X  unsigned  quit;
  656. X  unsigned  count;
  657. X
  658. X  monster.monsters = 0;
  659. X  apple.apples = 0;
  660. X  player.ball.state = 0;
  661. X  player.ball.count = 8;
  662. X  XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  663. X      0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  664. X  /*{{{  put on M R I S*/
  665. X  {
  666. X    unsigned  missing;
  667. X    unsigned  index;
  668. X    int       x, y;
  669. X      
  670. X    missing = random() & 3;
  671. X    for(index = 4; index--;)
  672. X      {
  673. X    SPRITE    *sptr;
  674. X      
  675. X    sptr = &sprites[SPRITE_MRIS + index + 4 * (index == missing)];
  676. X    XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  677. X        0, 0, CELL_WIDTH, CELL_HEIGHT,
  678. X        PIXELX(4 + index, 0), PIXELY(-1, 0));
  679. X    XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  680. X        0, 0, CELL_WIDTH, CELL_HEIGHT,
  681. X        PIXELX(4 + index, 0), PIXELY(-1, 0));
  682. X      }
  683. X    y = random() % (CELLS_DOWN + 2) * (CELL_HEIGHT + GAP_HEIGHT);
  684. X    x = random() & 1 ? CELLS_ACROSS * (CELL_WIDTH + GAP_WIDTH) :
  685. X    -CELLS_ACROSS * (CELL_WIDTH + GAP_WIDTH);
  686. X    spawn_monster(SPRITE_MRIS + missing, 0, 0, 4 + missing, -1, x, y);
  687. X  }
  688. X  /*}}}*/
  689. X  XCopyArea(display.display, display.back, display.copy, GCN(GC_COPY),
  690. X      0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
  691. X  /*{{{  put on the title text*/
  692. X  {
  693. X    char const **tptr;
  694. X    unsigned  length;
  695. X    unsigned  index;
  696. X    unsigned  gnome;
  697. X      
  698. X    gnome = 0;
  699. X    for(tptr = title_text, index = 0; *tptr; tptr++, index++)
  700. X      {
  701. X    length = strlen(*tptr);
  702. X    if(length)
  703. X      {
  704. X        TEXT      info;
  705. X        char  const *ptr;
  706. X        unsigned  shift;
  707. X          
  708. X        ptr = strchr(*tptr, '-');
  709. X        if(ptr)
  710. X          {
  711. X        text_size(*tptr, ptr - *tptr + 1, &info);
  712. X        shift = info.width;
  713. X          }
  714. X        else
  715. X          shift = 0;
  716. X        text_size(*tptr, length, &info);
  717. X        XDrawImageString(display.display, display.back, GCN(GC_TEXT),
  718. X        WINDOW_WIDTH / 2 - (shift ? shift : info.width / 2),
  719. X        PIXELY(index, CELL_HEIGHT / 2) +
  720. X        (info.ascent - info.descent) / 2, *tptr, length);
  721. X        /*{{{  spawn monster*/
  722. X        {
  723. X          unsigned  type;
  724. X          int       cellx;
  725. X          int       offsetx;
  726. X                
  727. X          do
  728. X        {
  729. X          type = random() & 3;
  730. X          if(type & 2)
  731. X            type++;
  732. X        }
  733. X          while(type == 4 && gnome);
  734. X          if(type == 4)
  735. X        gnome = 1;
  736. X          if(random() & 1)
  737. X        {
  738. X          cellx = -2;
  739. X          offsetx = (CELLS_ACROSS + 2) * (CELL_WIDTH + GAP_WIDTH);
  740. X        }
  741. X          else
  742. X        {
  743. X          cellx = CELLS_ACROSS + 1;
  744. X          offsetx = -(CELLS_ACROSS + 5) * (CELL_WIDTH + GAP_WIDTH);
  745. X        }
  746. X          offsetx += CELL_WIDTH * (random() & 3);
  747. X          spawn_monster(type, 0, 0, cellx, index, offsetx, 0);
  748. X        }
  749. X        /*}}}*/
  750. X      }
  751. X      }
  752. X  }
  753. X  /*}}}*/
  754. X  count = DISPLAY_HOLD;
  755. X  refresh_window();
  756. X  timer_start(FRAME_RATE);
  757. X  while(count)
  758. X    {
  759. X      quit = process_xevents(0);
  760. X      if(quit)
  761. X    {
  762. X      player.button = 1;
  763. X      break;
  764. X    }
  765. X      if(!move_demo())
  766. X    count--;
  767. X      if(player.button)
  768. X    count = 0;
  769. X      show_updates();
  770. X      timer_wait();
  771. X      }
  772. X  timer_stop();
  773. X  return quit;
  774. }
  775. /*}}}*/
  776. /*{{{  int demo_mode()*/
  777. extern int demo_mode FUNCARGVOID
  778. {
  779. X  unsigned  quit;
  780. X
  781. X  global.state = 6;
  782. X  player.keyboard = 0;
  783. X  player.button = 0;
  784. X  player.pressed = 0;
  785. X  player.old_ball.state = 0;
  786. X  quit = 0;
  787. X  while(!player.button)
  788. X    {
  789. X      if(!player.button)
  790. X    quit = demo_keys();
  791. X      if(!player.button)
  792. X    quit = demo_board();
  793. X    }
  794. X  player.button = 0;
  795. X  return quit;
  796. }
  797. /*}}}*/
  798. /*{{{  void extra_life()*/
  799. extern void extra_life FUNCARGVOID
  800. /* does the extra life senario */
  801. {
  802. X  static char const *text[] = {"Congratulations", "You win extra", NULL};
  803. X  unsigned  thrown;
  804. X  
  805. X  add_background(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  806. X  XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  807. X      BORDER_LEFT + 1, BORDER_TOP + 1, BOARD_WIDTH - 2, BOARD_HEIGHT - 2);
  808. X  /*{{{  display some text*/
  809. X  {
  810. X    unsigned  line;
  811. X    TEXT      info;
  812. X    char const **tptr;
  813. X    unsigned  length;
  814. X      
  815. X    line = BORDER_TOP + CELL_HEIGHT;
  816. X    for(tptr = text; *tptr; tptr++)
  817. X      {
  818. X    length = strlen(*tptr);
  819. X    text_size(*tptr, length, &info);
  820. X    XDrawImageString(display.display, display.back, GCN(GC_TEXT),
  821. X        WINDOW_WIDTH / 2 - info.width / 2,
  822. X        line + info.ascent, *tptr, length);
  823. X    line += info.ascent + info.descent;
  824. X      }
  825. X  }
  826. X  /*}}}*/
  827. X  monster.monsters = 0;
  828. X  apple.apples = 0;
  829. X  spawn_monster(4, 3, 3, 3, DEN_Y, -(CELL_WIDTH + GAP_WIDTH) * 3, 0);
  830. X  spawn_monster(0, 2, 2, 0, DEN_Y,
  831. X      (CELLS_ACROSS - 1) * (CELL_WIDTH + GAP_WIDTH), 0);
  832. X  /*{{{  add m r i s*/
  833. X  {
  834. X    unsigned  i;
  835. X    for(i = 4; i--;)
  836. X      {
  837. X    XCopyArea(display.display, sprites[SPRITE_MRIS + 4 + i].mask,
  838. X        display.back, GCN(GC_MASK), 0, 0, CELL_WIDTH, CELL_HEIGHT,
  839. X        PIXELX(CELLS_ACROSS / 2 - 2 + i, 0), PIXELY(2, 0));
  840. X    XCopyArea(display.display, sprites[SPRITE_MRIS + 4 + i].image,
  841. X        display.back, GCN(GC_OR), 0, 0, CELL_WIDTH, CELL_HEIGHT,
  842. X        PIXELX(CELLS_ACROSS / 2 - 2 + i, 0), PIXELY(2, 0));
  843. X    spawn_monster(SPRITE_MRIS + i, 1, 1, CELLS_ACROSS / 2 - 2 + i,
  844. X        2, 0, -(CELL_HEIGHT + GAP_HEIGHT) * 3 - CELL_HEIGHT / 2 * i);
  845. X      }
  846. X  }
  847. X  /*}}}*/
  848. X  draw_extra_letter(extra.select);
  849. X  player.pressed = 0;
  850. X  /*{{{  create a path*/
  851. X  {
  852. X    unsigned  i;
  853. X    CELL      *cptr;
  854. X    
  855. X    apple.apples = 0;
  856. X    for(cptr = BOARDCELL(0, DEN_Y), i = CELLS_ACROSS; i--; cptr++)
  857. X      {
  858. X    cptr->visit = 1;
  859. X    cptr->sprite = 0;
  860. X    cptr->distance = CELLS_ACROSS - i;
  861. X    cptr->depths[0] = 0;
  862. X    cptr->depths[1] = 0;
  863. X    cptr->depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  864. X    cptr->depths[3] = CELL_WIDTH + GAP_WIDTH;
  865. X      }
  866. X    BOARDCELL(0, DEN_Y)->depths[2] = 0;
  867. X    BOARDCELL(CELLS_ACROSS - 1, DEN_Y)->depths[3] = 0;
  868. X  }
  869. X  /*}}}*/
  870. X  global.state = 5;
  871. X  thrown = 0;
  872. X  while(thrown != 3)
  873. X    {
  874. X      process_xevents(1);
  875. X      if(!monster.list[0].offset.x && !thrown)
  876. X    {
  877. X      thrown = 1;
  878. X      player.throw = 1;
  879. X    }
  880. X      bounce_ball();
  881. X      if(player.ball.state == 3)
  882. X    player.ball.state = 4;
  883. X      else if(player.ball.state == 4)
  884. X    {
  885. X      player.ball.pixel.x = PIXELX(player.lives - 1, 0) + CELL_WIDTH / 2;
  886. X      player.ball.pixel.y = BORDER_TOP + BOARD_HEIGHT + 1 +
  887. X          CELL_HEIGHT / 2 - (CELL_HEIGHT + GAP_HEIGHT) * 3;
  888. X    }
  889. X      else if(!player.ball.state && thrown == 1)
  890. X    {
  891. X      spawn_monster(SPRITE_PLAYER + 6, 0, 1, player.lives - 1, CELLS_DOWN,
  892. X          0, -(CELL_HEIGHT + GAP_HEIGHT) * 3);
  893. X      thrown = 2;
  894. X    }
  895. X      if(!move_demo() && thrown == 2)
  896. X    thrown = 3;
  897. X      show_updates();
  898. X      timer_wait();
  899. X    }
  900. X  XCopyArea(display.display, display.copy, display.back, GCN(GC_COPY),
  901. X      PIXELX(player.lives - 1, 0), PIXELY(CELLS_DOWN, 0),
  902. X      CELL_WIDTH, CELL_HEIGHT,
  903. X      PIXELX(player.lives - 1, 0), PIXELY(CELLS_DOWN, 0));
  904. X  player.lives++;
  905. X  return;
  906. }
  907. /*}}}*/
  908. /*{{{  int move_demo()*/
  909. static int move_demo FUNCARGVOID
  910. /*
  911. X * moves the monsters used in the demo screens
  912. X * we take each monster with a non-zero offset, and move it
  913. X * towards a zero offset (changing x first)
  914. X * it might get blown up by the ball
  915. X * returns the number of objects which moved
  916. X */
  917. {
  918. X  MONSTER   *mptr;
  919. X  unsigned  i;
  920. X  unsigned  moved;
  921. X
  922. X  moved = 0;
  923. X  for(mptr = monster.list, i = monster.monsters; i--; mptr++)
  924. X    {
  925. X      if(mptr->shot)
  926. X    mptr->type = 5;
  927. X      else
  928. X    {
  929. X      if(mptr->offset.x)
  930. X        /*{{{  left or right*/
  931. X        {
  932. X          int       dir;
  933. X                
  934. X          moved++;
  935. X          if(mptr->offset.x > 0)
  936. X        {
  937. X          dir = 2;
  938. X          mptr->offset.x -= VEL_X;
  939. X          mptr->pixel.x -= VEL_X;
  940. X        }
  941. X          else
  942. X        {
  943. X          dir = 3;
  944. X          mptr->offset.x += VEL_X;
  945. X          mptr->pixel.x += VEL_X;
  946. X        }
  947. X          if(dir != mptr->dir)
  948. X        {
  949. X          mptr->dir = dir;
  950. X          new_face(mptr);
  951. X        }
  952. X                  
  953. X        }
  954. X        /*}}}*/
  955. X      else if(mptr->offset.y)
  956. X        /*{{{  up or down*/
  957. X        {
  958. X          int       dir;
  959. X                
  960. X          moved++;
  961. X          if(mptr->offset.y > 0)
  962. X        {
  963. X          dir = 0;
  964. X          mptr->offset.y -= VEL_Y;
  965. X          mptr->pixel.y -= VEL_Y;
  966. X        }
  967. X          else
  968. X        {
  969. X          dir = 1;
  970. X          mptr->offset.y += VEL_Y;
  971. X          mptr->pixel.y += VEL_Y;
  972. X        }
  973. X          if(dir != mptr->dir)
  974. X        {
  975. X          mptr->dir = dir;
  976. X          new_face(mptr);
  977. X        }
  978. X                  
  979. X        }
  980. X        /*}}}*/
  981. X      else
  982. X        mptr->stop = 1;
  983. X      if(!mptr->stop)
  984. X        {
  985. X          if(!mptr->cycle)
  986. X        {
  987. X          mptr->cycle = MONSTER_CYCLES;
  988. X          mptr->image++;
  989. X          if(mptr->image == MONSTER_IMAGES)
  990. X            mptr->image = 0;
  991. X        }
  992. X          mptr->cycle--;
  993. X        }
  994. X    }
  995. X    
  996. X    }
  997. X  return moved;
  998. }
  999. /*}}}*/
  1000. /*{{{  void move_mris()*/
  1001. static void move_mris FUNCARGVOID
  1002. /*
  1003. X * moves M R I S sprites around the board
  1004. X * towards the top
  1005. X */
  1006. {
  1007. X  unsigned  i;
  1008. X  MONSTER   *mptr;
  1009. X
  1010. X  for(mptr = &monster.list[1], i = monster.monsters - 1; i--; mptr++)
  1011. X    {
  1012. X      CELL      *cptr;
  1013. X    
  1014. X      assert(mptr->type >= SPRITE_MRIS && mptr->type < SPRITE_MRIS + 8);
  1015. X      cptr = BOARDCELL(mptr->cell.x, mptr->cell.y);
  1016. X      if(mptr->offset.x || mptr->offset.y)
  1017. X    move_movable(mptr, cptr);
  1018. X      else if(!mptr->cell.y && mptr->cell.x == 4 + i)
  1019. X    {
  1020. X      if(monster.den == i)
  1021. X        monster.den = i + 1;
  1022. X    }
  1023. X      else
  1024. X    {
  1025. X      unsigned  valid;
  1026. X      unsigned  temp;
  1027. X      
  1028. X      valid = valid_directions(mptr, cptr);
  1029. X      temp = valid & (0xF ^ (1 << (mptr->dir ^ 1)));
  1030. X      if(temp)
  1031. X        valid &= temp | 0xF0;
  1032. X      if(monster.den == i && (temp = valid & (valid >> 4)))
  1033. X        valid = temp;
  1034. X      else
  1035. X        valid &= 0xF;
  1036. X      mptr->dir = choose_direction(valid);
  1037. X      move_movable(mptr, cptr);
  1038. X    }
  1039. X    }
  1040. X  return;
  1041. }
  1042. /*}}}*/
  1043. /*{{{  void show_history()*/
  1044. extern void show_history FUNCARGVOID
  1045. /* shows the history list */
  1046. {
  1047. X  unsigned  count;
  1048. X  
  1049. X  add_background(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  1050. X  draw_extra_letter(extra.select);
  1051. X  XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1052. X      BORDER_LEFT + 1, BORDER_TOP + 1, BOARD_WIDTH - 2, BOARD_HEIGHT - 2);
  1053. X  monster.monsters = 0;
  1054. X  apple.apples = 0;
  1055. X  player.ball.state = 0;
  1056. X  player.ball.count = 8;
  1057. X  player.old_ball.state = 0;
  1058. X  /*{{{  add in the parts*/
  1059. X  {
  1060. X    unsigned  base;
  1061. X    unsigned  screens;
  1062. X    unsigned  index;
  1063. X    TEXT      info;
  1064. X    char      text[11];
  1065. X    unsigned  length;
  1066. X    static int sprites[3] = {SPRITE_CHERRY, SPRITE_NORMAL + 4, SPRITE_PLAYER + 4};
  1067. X      
  1068. X    screens = player.screen < CELLS_DOWN - 2 ? player.screen : CELLS_DOWN - 2;
  1069. X    base = player.screen - screens;
  1070. X    text_size("Screen 090", 10, &info);
  1071. X    for(index = screens; index--;)
  1072. X      {
  1073. X    sprintf(text, "Screen %d", base + index + 1);
  1074. X    length = strlen(text);
  1075. X    XDrawImageString(display.display, display.back, GCN(GC_TEXT),
  1076. X        PIXELX(CELLS_ACROSS / 2, -GAP_WIDTH) - info.width,
  1077. X        PIXELY(screens - index, (CELL_HEIGHT + GAP_HEIGHT) / 2) +
  1078. X        (info.ascent - info.descent) / 2,
  1079. X        text, length);
  1080. X    if(history.prize & 1 << (screens - 1 - index))
  1081. X      spawn_monster(SPRITE_PRIZE_BASE +
  1082. X          (base + index) % SPRITE_PRIZES, 0, 0,
  1083. X          CELLS_ACROSS / 2 + 2, screens - index,
  1084. X          0, index * (2 * CELL_HEIGHT + GAP_HEIGHT) +
  1085. X          CELLS_DOWN * GAP_HEIGHT + CELL_HEIGHT / 2 + GAP_HEIGHT +
  1086. X          (CELL_HEIGHT + GAP_HEIGHT) * (2 + CELLS_DOWN - screens));
  1087. X    spawn_monster(sprites[(history.ending >>
  1088. X        (screens - 1 - index) * 2) & 3],
  1089. X        0, 0, CELLS_ACROSS / 2, screens - index,
  1090. X        0, index * (2 * CELL_HEIGHT + GAP_HEIGHT) +
  1091. X        CELLS_DOWN * GAP_HEIGHT + 
  1092. X        (CELL_HEIGHT + GAP_HEIGHT) * (2 + CELLS_DOWN - screens));
  1093. X      }
  1094. X  }
  1095. X  /*}}}*/
  1096. X  global.state = 8;
  1097. X  count = DISPLAY_HOLD;
  1098. X  while(count)
  1099. X    {
  1100. X      process_xevents(1);
  1101. X      if(!move_demo())
  1102. X    count--;
  1103. X      show_updates();
  1104. X      timer_wait();
  1105. X    }
  1106. X  return;
  1107. }
  1108. /*}}}*/
  1109. SHAR_EOF
  1110. chmod 0644 demo.c ||
  1111. echo 'restore of demo.c failed'
  1112. Wc_c="`wc -c < 'demo.c'`"
  1113. test 13731 -eq "$Wc_c" ||
  1114.     echo 'demo.c: original size 13731, current size' "$Wc_c"
  1115. rm -f _shar_wnt_.tmp
  1116. fi
  1117. # ============= draw.c ==============
  1118. if test -f 'draw.c' -a X"$1" != X"-c"; then
  1119.     echo 'x - skipping draw.c (File already exists)'
  1120.     rm -f _shar_wnt_.tmp
  1121. else
  1122. > _shar_wnt_.tmp
  1123. echo 'x - extracting draw.c (Text)'
  1124. sed 's/^X//' << 'SHAR_EOF' > 'draw.c' &&
  1125. /*{{{  (C) 1992 Nathan Sidwell*/
  1126. /*****************************************************************************
  1127. X            X M R I S V1.01
  1128. X            ---------------
  1129. X            (C) 1992 Nathan Sidwell
  1130. X
  1131. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  1132. is in the public domain. Permission is granted to distribute and compile
  1133. verbatim copies of this software for non-commercial, non-profit use,
  1134. without fee. The software may be modified, provided that both the above copyright
  1135. notice and this permission notice appear.
  1136. X
  1137. No guarantee is given as to the robustness or suitability of this
  1138. software for your computer.
  1139. X
  1140. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  1141. *****************************************************************************/
  1142. /*}}}*/
  1143. #include "xmris.h"
  1144. #include "time.h"
  1145. /*{{{  prototypes*/
  1146. static void xor_ball PROTOARGLIST((void));
  1147. /*}}}*/
  1148. /*{{{  void add_background(x, y, w, h)*/
  1149. extern void add_background FUNCARGLIST((x, y, width, height))
  1150. int       x       FUNCARGSEP
  1151. int       y       FUNCARGSEP
  1152. int       width   FUNCARGSEP
  1153. int       height  FUNCARGTERM
  1154. /*
  1155. X * adds an area to the background update list
  1156. X */
  1157. {
  1158. X  BACKGROUND *bptr;
  1159. X
  1160. X  assert(update.back.backs != BACK_UPDATES);
  1161. X  bptr = &update.back.list[update.back.backs++];
  1162. X  bptr->place.x = x;
  1163. X  bptr->place.y = y;
  1164. X  bptr->size.x = width;
  1165. X  bptr->size.y = height;
  1166. X  return;
  1167. }
  1168. /*}}}*/
  1169. /*{{{  void bounding_box(x, y, width, height)*/
  1170. extern void bounding_box FUNCARGLIST((x, y, width, height))
  1171. int       x       FUNCARGSEP
  1172. int       y       FUNCARGSEP
  1173. unsigned  width   FUNCARGSEP
  1174. unsigned  height  FUNCARGTERM
  1175. /*
  1176. X * updates the update box so that it includes the
  1177. X * supplied rectangle/
  1178. X * remember to empty the update box to the background list
  1179. X */
  1180. {
  1181. X  if(!update.set)
  1182. X    {
  1183. X      update.br.x = (update.tl.x = x) + width;
  1184. X      update.br.y = (update.tl.y = y) + height;
  1185. X      update.set = 1;
  1186. X    }
  1187. X  else
  1188. X    {
  1189. X      if(update.tl.x > x)
  1190. X    update.tl.x = x;
  1191. X      if(update.tl.y > y)
  1192. X    update.tl.y = y;
  1193. X      if(update.br.x < (int)(x + width))
  1194. X    update.br.x = (int)(x + width);
  1195. X      if(update.br.y < (int)(y + height))
  1196. X    update.br.y = (int)(y + height);
  1197. X    }
  1198. X  return;
  1199. }
  1200. /*}}}*/
  1201. /*{{{  void draw_center(index)*/
  1202. extern void draw_center FUNCARGLIST((index))
  1203. int   index FUNCARGTERM
  1204. /*
  1205. X * sets the center sprite and draws it on the background
  1206. X */
  1207. {
  1208. X  SPRITE    *sptr;
  1209. X
  1210. X  BOARDCELL(DEN_X, DEN_Y)->sprite = index;
  1211. X  add_background(PIXELX(DEN_X, 0), PIXELY(DEN_Y, 0), CELL_WIDTH, CELL_HEIGHT);
  1212. X  XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1213. X      PIXELX(DEN_X, 0), PIXELY(DEN_Y, 0), CELL_WIDTH, CELL_HEIGHT);
  1214. X  sptr = &sprites[index];
  1215. X  if(display.background != COLOUR_ZERO)
  1216. X    XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  1217. X    0, 0, CELL_WIDTH, CELL_HEIGHT, PIXELX(DEN_X, 0), PIXELY(DEN_Y, 0));
  1218. X  XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  1219. X      0, 0, CELL_WIDTH, CELL_HEIGHT, PIXELX(DEN_X, 0), PIXELY(DEN_Y, 0));
  1220. X  return;
  1221. }
  1222. /*}}}*/
  1223. /*{{{  void draw_extra()*/
  1224. extern void draw_extra FUNCARGVOID
  1225. {
  1226. X  int       x;
  1227. X  SPRITE    *sptr;
  1228. X  
  1229. X  x = XTRA_X + extra.select * XTRA_SPACING;
  1230. X  sptr = &sprites[SPRITE_XTRA + (random() & 1)];
  1231. X  XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  1232. X      0, 0, CELL_WIDTH, CELL_HEIGHT, x, XTRA_Y);
  1233. X  XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  1234. X      0, 0, CELL_WIDTH, CELL_HEIGHT, x, XTRA_Y);
  1235. X  add_background(x, XTRA_Y, CELL_WIDTH, CELL_HEIGHT);
  1236. X  return;
  1237. }
  1238. /*}}}*/
  1239. /*{{{  void new_board()*/
  1240. extern void new_board FUNCARGVOID
  1241. /*
  1242. X * sets up a new board
  1243. X */
  1244. {
  1245. X  BOARD const *map;
  1246. X
  1247. X  player.screen++;
  1248. X  map = &boards[player.screen % BOARDS];
  1249. X  /*{{{  clear board array*/
  1250. X  {
  1251. X    unsigned  i;
  1252. X    CELL      *ptr;
  1253. X    
  1254. X    for(i = sizeof(board) / sizeof(board[0]), ptr = board; i--; ptr++)
  1255. X      {
  1256. X    ptr->depths[0] = 0;
  1257. X    ptr->depths[1] = 0;
  1258. X    ptr->depths[2] = 0;
  1259. X    ptr->depths[3] = 0;
  1260. X    ptr->visit = 0;
  1261. X    ptr->distance = 0;
  1262. X    ptr->sprite = 0;
  1263. X      }
  1264. X  }
  1265. X  /*}}}*/
  1266. X  /*{{{  draw blank background*/
  1267. X  {
  1268. X    /*{{{  set context*/
  1269. X    {
  1270. X      XGCValues gcv;
  1271. X      
  1272. X      gcv.fill_style = FillTiled;
  1273. X      gcv.tile = sprites[SPRITE_FILL_BASE + map->fill].image;
  1274. X      XChangeGC(display.display, GCN(GC_BOARD), GCTile | GCFillStyle, &gcv);
  1275. X    }
  1276. X    /*}}}*/
  1277. X    XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1278. X    0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
  1279. X    XFillRectangle(display.display, display.back, GCN(GC_BOARD),
  1280. X    BORDER_LEFT, BORDER_TOP, BOARD_WIDTH, BOARD_HEIGHT);
  1281. X    XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1282. X    PIXELX(DEN_X, -GAP_WIDTH / 2), PIXELY(DEN_Y, -GAP_HEIGHT / 2),
  1283. X    CELL_WIDTH + GAP_WIDTH, CELL_HEIGHT + GAP_HEIGHT);
  1284. X    XFillRectangle(display.display, display.back, GCN(GC_CLEAR),
  1285. X    BORDER_LEFT + (CELL_WIDTH + GAP_WIDTH) * 4 + GAP_WIDTH, BORDER_TOP,
  1286. X    XTRA_SPACING * 4 + CELL_WIDTH, GAP_HEIGHT * 2);
  1287. X    XDrawRectangle(display.display, display.back, GCN(GC_SET),
  1288. X    XTRA_X - 1, XTRA_Y - 1,
  1289. X    XTRA_SPACING * 4 + CELL_WIDTH + 1, CELL_HEIGHT + 1);
  1290. X    XDrawRectangle(display.display, display.back, GCN(GC_SET),
  1291. X    BORDER_LEFT, BORDER_TOP,
  1292. X    BOARD_WIDTH - 1, BOARD_HEIGHT - 1);
  1293. X  }
  1294. X  /*}}}*/
  1295. X  /*{{{  add the xtra*/
  1296. X  {
  1297. X    unsigned  i;
  1298. X      
  1299. X    extra.escape = 0;
  1300. X    for(i = 5; i--;)
  1301. X      draw_extra_letter(i);
  1302. X    draw_extra();
  1303. X  }
  1304. X  /*}}}*/
  1305. X  /*{{{  add the screen number*/
  1306. X  {
  1307. X    char      text[10];
  1308. X    int       length;
  1309. X    int       ascent, descent;
  1310. X    int       direction;
  1311. X    XCharStruct chars;
  1312. X      
  1313. X    strcpy(text, "Screen ");
  1314. X    length = 7 + itoa(text + 7, player.screen, 0);
  1315. X    XQueryTextExtents(display.display, font.font, text, length,
  1316. X      &direction, &ascent, &descent, &chars);
  1317. X    XDrawImageString(display.display, display.back, GCN(GC_TEXT),
  1318. X    BORDER_LEFT + (CELL_WIDTH + GAP_WIDTH) * 8 +
  1319. X    CELL_WIDTH / 2 + GAP_WIDTH, (CELL_HEIGHT - ascent - descent) / 2 +
  1320. X    ascent + BORDER_TOP - CELL_HEIGHT, text, length);
  1321. X  }
  1322. X  /*}}}*/
  1323. X  add_score(0, 0, 0);
  1324. X  /*{{{  add lives*/
  1325. X  if(player.lives)
  1326. X    {
  1327. X      unsigned  lives;
  1328. X      SPRITE    *sptr;
  1329. X      
  1330. X      sptr = &sprites[SPRITE_PLAYER + 6];
  1331. X      for(lives = player.lives - 1; lives--;)
  1332. X    {
  1333. X      unsigned  x, y;
  1334. X        
  1335. X      x = PIXELX(lives, 0);
  1336. X      y = PIXELY(CELLS_DOWN, 0);
  1337. X      XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  1338. X          0, 0, CELL_WIDTH, CELL_HEIGHT, x, y);
  1339. X      XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  1340. X          0, 0, CELL_WIDTH, CELL_HEIGHT, x, y);
  1341. X    }
  1342. X    }
  1343. X  /*}}}*/
  1344. X  /*{{{  copy the map*/
  1345. X  {
  1346. X    char const *mptr;
  1347. X    CELL      *cptr;
  1348. X    unsigned  y, x;
  1349. X    
  1350. X    mptr = (char const *)map->map;
  1351. X    cptr = BOARDCELL(0, 0);
  1352. X    for(y = CELLS_DOWN; y--; cptr += CELL_STRIDE - CELLS_ACROSS)
  1353. X      for(x = CELLS_ACROSS; x--; mptr++, cptr++)
  1354. X    {
  1355. X      switch(*mptr)
  1356. X      {
  1357. X        /*{{{  case '@': (cherry)*/
  1358. X        case '@':
  1359. X          cptr->sprite = SPRITE_CHERRY;
  1360. X          break;
  1361. X        /*}}}*/
  1362. X        /*{{{  case 'X': (path)*/
  1363. X        case 'X':
  1364. X          cptr[0].visit = 1;
  1365. X          if(cptr[-1].visit)
  1366. X        {
  1367. X          cptr[-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  1368. X          cptr[0].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  1369. X        }
  1370. X          if(cptr[-CELL_STRIDE].visit)
  1371. X        {
  1372. X          cptr[-CELL_STRIDE].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  1373. X          cptr[0].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  1374. X        }
  1375. X          break;
  1376. X        /*}}}*/
  1377. X      }
  1378. X    }
  1379. X  }
  1380. X  /*}}}*/
  1381. X  /*{{{  add the apples*/
  1382. X  {
  1383. X    unsigned  i;
  1384. X    
  1385. X    apple.apples = 0;
  1386. X    for(i = INITIAL_APPLES; i--;)
  1387. X      {
  1388. X    unsigned  y, x;
  1389. X    unsigned  j;
  1390. X    CELL      *cptr;
  1391. X    APPLE     *aptr;
  1392. X      
  1393. X    do
  1394. X      {
  1395. X        do
  1396. X          j = random();
  1397. X        while(j >= CELLS_ACROSS * (CELLS_DOWN - 1));
  1398. X        x = j % CELLS_ACROSS;
  1399. X        y = j / CELLS_ACROSS;
  1400. X        cptr = BOARDCELL(x, y);
  1401. X        for(aptr = apple.list, j = apple.apples; j--; aptr++)
  1402. X          if(aptr->cell.x == x && aptr->cell.y == y)
  1403. X        {
  1404. X          aptr = NULL;
  1405. X          break;
  1406. X        }
  1407. X      }
  1408. X    while(cptr->visit || cptr->sprite || cptr[CELL_STRIDE].visit || !aptr);
  1409. X    spawn_apple(x, y, 0, 0);
  1410. X      }
  1411. X  }
  1412. X  /*}}}*/
  1413. X  /*{{{  cut the background*/
  1414. X  {
  1415. X    unsigned  y, x;
  1416. X    COORD     cell;
  1417. X    CELL      *cptr;
  1418. X    
  1419. X    cptr = BOARDCELL(0, 0);
  1420. X    cell.x = GAP_WIDTH + BORDER_LEFT;
  1421. X    cell.y = GAP_HEIGHT + BORDER_TOP;
  1422. X    for(y = CELLS_DOWN; y--; cptr += CELL_STRIDE - CELLS_ACROSS,
  1423. X    cell.x -= (CELL_WIDTH + GAP_WIDTH) * CELLS_ACROSS,
  1424. X    cell.y += CELL_HEIGHT + GAP_HEIGHT)
  1425. X      for(x = CELLS_ACROSS; x--; cptr++, cell.x += CELL_WIDTH + GAP_WIDTH)
  1426. X    if(cptr->visit)
  1427. X      munch_hole(cptr, cell.x, cell.y);
  1428. X    else if(cptr->sprite)
  1429. X      {
  1430. X        SPRITE    *sptr;
  1431. X      
  1432. X        sptr = &sprites[SPRITE_CHERRY];
  1433. X        XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  1434. X        0, 0, CELL_WIDTH, CELL_HEIGHT, cell.x, cell.y);
  1435. X        XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  1436. X        0, 0, CELL_WIDTH, CELL_HEIGHT, cell.x, cell.y);
  1437. X      }
  1438. X  }
  1439. X  /*}}}*/
  1440. X  /*{{{  initialize stuff*/
  1441. X  {
  1442. X    global.cherries = 5 * 8;
  1443. X    global.difficulty = player.screen + DIFFICULTY_PEDESTAL;
  1444. X    monster.normals = player.screen >= 3 ? 8 : 6;
  1445. X    update.back.backs = 0;
  1446. X    update.score.scores = 0;
  1447. X  }
  1448. X  /*}}}*/
  1449. X  XCopyArea(display.display, display.back, display.copy, GCN(GC_COPY),
  1450. X      0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
  1451. X  return;
  1452. }
  1453. /*}}}*/
  1454. /*{{{  void refresh_window()*/
  1455. extern void refresh_window FUNCARGVOID
  1456. /*
  1457. X * refreshes the display window
  1458. X */
  1459. {
  1460. X  XCopyArea(display.display, display.copy, display.window, GCN(GC_COPY), 
  1461. X      0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0);
  1462. X  xor_ball();
  1463. X  XDrawLine(display.display, display.window, GCN(GC_BALL),
  1464. X      WINDOW_WIDTH - global.missed, WINDOW_HEIGHT - 1,
  1465. X      WINDOW_WIDTH, WINDOW_HEIGHT - 1);
  1466. X  return;
  1467. }
  1468. /*}}}*/
  1469. /*{{{  void show_updates()*/
  1470. extern void show_updates FUNCARGVOID
  1471. /*
  1472. X * shows all the updates on the update list
  1473. X */
  1474. {
  1475. X  xor_ball();
  1476. X  /*{{{  backgrounds to copy*/
  1477. X  {
  1478. X    unsigned  i;
  1479. X    BACKGROUND *bptr;
  1480. X    
  1481. X    for(bptr = update.back.list, i = update.back.backs; i--; bptr++)
  1482. X      XCopyArea(display.display, display.back, display.copy, GCN(GC_COPY),
  1483. X      bptr->place.x, bptr->place.y, bptr->size.x, bptr->size.y,
  1484. X      bptr->place.x, bptr->place.y);
  1485. X  }
  1486. X  /*}}}*/
  1487. X  /*{{{  do the monster backgrounds*/
  1488. X  {
  1489. X    int       i;
  1490. X    MONSTER   *mptr;
  1491. X      
  1492. X    for(mptr = monster.list, i = monster.monsters; i--; mptr++)
  1493. X      {
  1494. X    int   new;
  1495. X      
  1496. X    update.set = 0;
  1497. X    if(mptr->type == 5)
  1498. X      new = 0;
  1499. X    else if(mptr->type > 5)
  1500. X      new = mptr->type;
  1501. X    else if(mptr->chew)
  1502. X      new = SPRITE_CHOMP + mptr->image;
  1503. X    else if(mptr->face >= 8)
  1504. X      new = SPRITE_SQUISHED - 8 + mptr->type * 2 + mptr->face;
  1505. X    else
  1506. X      new = SPRITE_MONSTERS + mptr->type * (6 * MONSTER_IMAGES) +
  1507. X          mptr->face * MONSTER_IMAGES + mptr->image;
  1508. X    if(mptr->old_sprite && (new != mptr->old_sprite ||
  1509. X        mptr->pixel.x != mptr->old_pixel.x ||
  1510. X        mptr->pixel.y != mptr->old_pixel.y ||
  1511. X        (mptr == &monster.list[0] &&
  1512. X          !player.old_ball.state && player.ball.state)))
  1513. X      {
  1514. X        XCopyArea(display.display, display.back, display.copy, GCN(GC_COPY),
  1515. X        mptr->old_pixel.x, mptr->old_pixel.y, CELL_WIDTH, CELL_HEIGHT,
  1516. X        mptr->old_pixel.x, mptr->old_pixel.y);
  1517. X        if(mptr->pixel.x != mptr->old_pixel.x ||
  1518. X        mptr->pixel.y != mptr->old_pixel.y || !new)
  1519. X          bounding_box(mptr->old_pixel.x, mptr->old_pixel.y,
  1520. X          CELL_WIDTH, CELL_HEIGHT);
  1521. X      }
  1522. X    if(new)
  1523. X      {
  1524. X        mptr->old_pixel.x = mptr->pixel.x;
  1525. X        mptr->old_pixel.y = mptr->pixel.y;
  1526. X        mptr->old_sprite = new;
  1527. X        bounding_box(mptr->old_pixel.x, mptr->old_pixel.y,
  1528. X        CELL_WIDTH, CELL_HEIGHT);
  1529. X      }
  1530. X    else
  1531. X      {
  1532. X        memmove(mptr, mptr + 1, i * sizeof(MONSTER));
  1533. X        mptr--;
  1534. X        monster.monsters--;
  1535. X      }
  1536. X    if(update.set)
  1537. X      add_background(update.tl.x, update.tl.y,
  1538. X          update.br.x - update.tl.x, update.br.y - update.tl.y);
  1539. X      }
  1540. X  }
  1541. X  /*}}}*/
  1542. X  /*{{{  do the apple backgrounds*/
  1543. X  {
  1544. X    int       i;
  1545. X    APPLE     *aptr;
  1546. X      
  1547. X    for(aptr = apple.list, i = apple.apples; i--; aptr++)
  1548. X      {
  1549. X    int   new;
  1550. X      
  1551. X    update.set = 0;
  1552. X    new = aptr->state;
  1553. X    if(new != aptr->old_state || aptr->pixel.x != aptr->old_pixel.x ||
  1554. X        aptr->pixel.y != aptr->old_pixel.y)
  1555. X      {
  1556. X        APPLE_SIZE const *asp;
  1557. X        int       x, y;
  1558. X        int       width, height;
  1559. X      
  1560. X        asp = &apple_sizes[aptr->old_state];
  1561. X        x = aptr->old_pixel.x + asp->offset.x;
  1562. X        y = aptr->old_pixel.y + asp->offset.y;
  1563. X        width = asp->size.x;
  1564. X        height = asp->size.y;
  1565. X        XCopyArea(display.display, display.back, display.copy, GCN(GC_COPY),
  1566. X        x, y, width, height, x, y);
  1567. X        bounding_box(x, y, width, height);
  1568. X      }
  1569. X    if(new != 6)
  1570. X      {
  1571. X        APPLE_SIZE const *asp;
  1572. X          
  1573. X        aptr->old_pixel.x = aptr->pixel.x;
  1574. X        aptr->old_pixel.y = aptr->pixel.y;
  1575. X        aptr->old_state = new;
  1576. X        asp = &apple_sizes[new];
  1577. X        bounding_box(aptr->old_pixel.x + asp->offset.x,
  1578. X        aptr->old_pixel.y + asp->offset.y, asp->size.x, asp->size.y);
  1579. X      }
  1580. X    else
  1581. X      {
  1582. X        unsigned  j;
  1583. X        MONSTER   *mptr;
  1584. X      
  1585. X        for(mptr = monster.list, j =  monster.monsters; j--; mptr++)
  1586. X          if(!mptr->apple)
  1587. X        /*EMPTY*/;
  1588. X          else if(mptr->apple == aptr)
  1589. X        mptr->apple = NULL;
  1590. X          else if(mptr->apple > aptr)
  1591. X        mptr->apple--;
  1592. X        memmove(aptr, aptr + 1, i * sizeof(APPLE));
  1593. X        aptr--;
  1594. X        apple.apples--;
  1595. X      }
  1596. X    if(update.set)
  1597. X      add_background(update.tl.x, update.tl.y,
  1598. X          update.br.x - update.tl.x, update.br.y - update.tl.y);
  1599. X      }
  1600. X  }
  1601. X  /*}}}*/
  1602. X  /*{{{  do the apple sprites*/
  1603. X  {
  1604. X    int       i;
  1605. X    APPLE     *aptr;
  1606. X      
  1607. X    for(aptr = apple.list, i = apple.apples; i--; aptr++)
  1608. X      {
  1609. X    SPRITE    *sptr;
  1610. X    APPLE_SIZE const *asp;
  1611. X    int       x, y;
  1612. X    int       width, height;
  1613. X      
  1614. X    asp = &apple_sizes[aptr->old_state];
  1615. X    sptr = &sprites[SPRITE_APPLE + aptr->old_state];
  1616. X    x = aptr->old_pixel.x + asp->offset.x;
  1617. X    y = aptr->old_pixel.y + asp->offset.y;
  1618. X    width = asp->size.x;
  1619. X    height = asp->size.y;
  1620. X    XCopyArea(display.display, sptr->mask, display.copy, GCN(GC_MASK),
  1621. X        0, 0, width, height, x, y);
  1622. X    XCopyArea(display.display, sptr->image, display.copy, GCN(GC_OR),
  1623. X        0, 0, width, height, x, y);
  1624. X      }
  1625. X  }
  1626. X  /*}}}*/
  1627. X  /*{{{  do the monster sprites*/
  1628. X  {
  1629. X    int       i;
  1630. X    MONSTER   *mptr;
  1631. X      
  1632. X    for(mptr = &monster.list[monster.monsters - 1], i = monster.monsters; i--; mptr--)
  1633. X      {
  1634. X    SPRITE    *sptr;
  1635. X      
  1636. X    sptr = &sprites[mptr->old_sprite];
  1637. X    XCopyArea(display.display, sptr->mask, display.copy, GCN(GC_MASK),
  1638. X        0, 0, CELL_WIDTH, CELL_HEIGHT,
  1639. X        mptr->old_pixel.x, mptr->old_pixel.y);
  1640. X    XCopyArea(display.display, sptr->image, display.copy, GCN(GC_OR),
  1641. X        0, 0, CELL_WIDTH, CELL_HEIGHT,
  1642. X        mptr->old_pixel.x, mptr->old_pixel.y);
  1643. X      }
  1644. X  }
  1645. X  /*}}}*/
  1646. X  /*{{{  holding the ball?*/
  1647. X  if(!player.ball.state && player.ball.count < 8)
  1648. X    {
  1649. X      COORD const *hold;
  1650. X      
  1651. X      hold = &ball_hold[player.ball.count * MONSTER_IMAGES + player.ball.image];
  1652. X      if(display.foreground == COLOUR_WEIRD)
  1653. X    XCopyArea(display.display, sprites[SPRITE_BALL].mask,
  1654. X        display.copy, GCN(GC_MASK), 0, 0, BALL_WIDTH, BALL_HEIGHT,
  1655. X        player.ball.pixel.x + hold->x, player.ball.pixel.y + hold->y);
  1656. X      XCopyArea(display.display, sprites[SPRITE_BALL].image,
  1657. X      display.copy, GCN(GC_OR), 0, 0, BALL_WIDTH, BALL_HEIGHT,
  1658. X      player.ball.pixel.x + hold->x, player.ball.pixel.y + hold->y);
  1659. X    }
  1660. X  /*}}}*/
  1661. X  /*{{{  scores to copy*/
  1662. X  {
  1663. X    unsigned  i;
  1664. X    SCORE     *sptr;
  1665. X      
  1666. X    for(sptr = update.score.list, i = update.score.scores; i--; sptr++)
  1667. X      {
  1668. X    XCopyArea(display.display, sptr->mask, display.copy, GCN(GC_MASK),
  1669. X        0, 0, DIGIT_WIDTH * 4, DIGIT_HEIGHT,
  1670. X        sptr->place.x, sptr->place.y);
  1671. X    XCopyArea(display.display, sptr->image, display.copy, GCN(GC_OR),
  1672. X        0, 0, DIGIT_WIDTH * 4, DIGIT_HEIGHT,
  1673. X        sptr->place.x, sptr->place.y);
  1674. X      }
  1675. X  }
  1676. X  /*}}}*/
  1677. X  /*{{{  areas to window*/
  1678. X  {
  1679. X    unsigned  i;
  1680. X    BACKGROUND *bptr;
  1681. X    
  1682. X    for(bptr = update.back.list, i = update.back.backs; i--; bptr++)
  1683. X      XCopyArea(display.display, display.copy, display.window, GCN(GC_COPY),
  1684. X      bptr->place.x, bptr->place.y, bptr->size.x, bptr->size.y,
  1685. X      bptr->place.x, bptr->place.y);
  1686. X  }
  1687. X  /*}}}*/
  1688. X  /*{{{  scores to window*/
  1689. X  {
  1690. X    unsigned  i;
  1691. X    SCORE     *sptr;
  1692. X      
  1693. X    for(sptr = update.score.list, i = update.score.scores; i--; sptr++)
  1694. X      XCopyArea(display.display, display.copy, display.window, GCN(GC_COPY),
  1695. X      sptr->place.x, sptr->place.y, DIGIT_WIDTH * 4, DIGIT_HEIGHT,
  1696. X      sptr->place.x, sptr->place.y);
  1697. X  }
  1698. X  /*}}}*/
  1699. X  update.back.backs = 0;
  1700. X  memcpy(&player.old_ball, &player.ball, sizeof(BALL));
  1701. X  xor_ball();
  1702. X  XSync(display.display, False);
  1703. X  return;
  1704. }
  1705. /*}}}*/
  1706. /*{{{  void text_size(text, length, tptr)*/
  1707. extern void text_size FUNCARGLIST((text, length, tptr))
  1708. char const *text  FUNCARGSEP
  1709. unsigned  length  FUNCARGSEP
  1710. TEXT      *tptr   FUNCARGTERM
  1711. /*
  1712. X * wraps up the XQueryTextExtents for us
  1713. X */
  1714. {
  1715. X  int       direction;
  1716. X  XCharStruct chars;
  1717. X  
  1718. X  XQueryTextExtents(display.display, font.font, text, length,
  1719. X      &direction, &tptr->ascent, &tptr->descent, &chars);
  1720. X  tptr->width = chars.width;
  1721. X  return;
  1722. }
  1723. /*}}}*/
  1724. /*{{{  void xor_ball()*/
  1725. static void xor_ball FUNCARGVOID
  1726. /*
  1727. X * draws the old ball on the window directly
  1728. X * using the ball's gc
  1729. X * if the ball is being held, then we don't draw it,
  1730. X * as that's done differently to stop it flickering
  1731. X */
  1732. {
  1733. X  switch(player.old_ball.state)
  1734. X  {
  1735. X    /*{{{  case 0:*/
  1736. X    case 0:
  1737. X      break;
  1738. X    /*}}}*/
  1739. X    /*{{{  case 1:*/
  1740. X    case 1:
  1741. X    {
  1742. X      XCopyArea(display.display, ball_xor, display.window, GCN(GC_BALL),
  1743. X      0, 0, BALL_WIDTH, BALL_HEIGHT,
  1744. X      player.old_ball.pixel.x - BALL_WIDTH / 2,
  1745. X      player.old_ball.pixel.y - BALL_HEIGHT / 2);
  1746. X      break;
  1747. X    }
  1748. X    /*}}}*/
  1749. X    /*{{{  case 2: case 4:*/
  1750. SHAR_EOF
  1751. true || echo 'restore of draw.c failed'
  1752. fi
  1753. echo 'End of  part 3'
  1754. echo 'File draw.c is continued in part 4'
  1755. echo 4 > _shar_seq_.tmp
  1756. exit 0
  1757. -- 
  1758. ---
  1759. Senior Systems Scientist        mail: dcmartin@msi.com
  1760. Molecular Simulations, Inc.        uucp: uunet!dcmartin
  1761. 796 North Pastoria Avenue        at&t: 408/522-9236
  1762.