home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / x / volume18 / xmris / part05 < prev    next >
Encoding:
Text File  |  1992-07-15  |  50.1 KB  |  1,893 lines

  1. Path: uunet!usc!elroy.jpl.nasa.gov!swrinde!mips!msi!dcmartin
  2. From: nathan@inmos.co.uk (Nathan Sidwell)
  3. Newsgroups: comp.sources.x
  4. Subject: v18i026: Xmris - an X video game, Part05/09
  5. Message-ID: <1992Jul16.171755.1827@msi.com>
  6. Date: 16 Jul 92 17:17:55 GMT
  7. References: <csx-18i022-xmris@uunet.UU.NET>
  8. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  9. Organization: Molecular Simulations, Inc.
  10. Lines: 1879
  11. Approved: dcmartin@msi.com
  12. Originator: dcmartin@fascet
  13.  
  14. Submitted-by: Nathan Sidwell <nathan@inmos.co.uk>
  15. Posting-number: Volume 18, Issue 26
  16. Archive-name: xmris/part05
  17.  
  18. # this is part.05 (part 5 of a multipart archive)
  19. # do not concatenate these parts, unpack them in order with /bin/sh
  20. # file move.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" != 5; 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 move.c'
  36. else
  37. echo 'x - continuing file move.c'
  38. sed 's/^X//' << 'SHAR_EOF' >> 'move.c' &&
  39. X        cptr[-CELL_STRIDE].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  40. X      }
  41. X    if(cptr[CELL_STRIDE].depths[0])
  42. X      {
  43. X        cptr[0].depths[1] = CELL_HEIGHT + GAP_HEIGHT;
  44. X        cptr[CELL_STRIDE].depths[0] = -(CELL_HEIGHT + GAP_HEIGHT);
  45. X      }
  46. X    if(cptr[-1].depths[3])
  47. X      {
  48. X        cptr[0].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  49. X        cptr[-1].depths[3] = CELL_WIDTH + GAP_WIDTH;
  50. X      }
  51. X    if(cptr[1].depths[2])
  52. X      {
  53. X        cptr[0].depths[3] = CELL_WIDTH + GAP_WIDTH;
  54. X        cptr[1].depths[2] = -(CELL_WIDTH + GAP_WIDTH);
  55. X      }
  56. X      }
  57. X      /*}}}*/
  58. X      munch_hole(cptr, pixel.x, pixel.y);
  59. X      /*{{{  now see if we launch any apples*/
  60. X      for(aptr = apple.list, i = apple.apples; i--; aptr++)
  61. X    {
  62. X      if(aptr->state > 1 || pixel.x - aptr->pixel.x > CELL_WIDTH / 2 ||
  63. X          pixel.x - aptr->pixel.x < -CELL_WIDTH / 2)
  64. X        /*EMPTY*/;
  65. X      else if(pixel.y - aptr->pixel.y > CELL_HEIGHT ||
  66. X          pixel.y - aptr->pixel.y < 0)
  67. X        /*EMPTY*/;
  68. X      else
  69. X        {
  70. X          /*{{{  move apple cell.x?*/
  71. X          if(aptr->cell.x < cell.x)
  72. X        {
  73. X          aptr->cell.x += 1;
  74. X          aptr->offset.x -= CELL_WIDTH + GAP_WIDTH;
  75. X        }
  76. X          else if(aptr->cell.x > cell.x)
  77. X        {
  78. X          aptr->cell.x -= 1;
  79. X          aptr->offset.x += CELL_WIDTH + GAP_WIDTH;
  80. X        }
  81. X          /*}}}*/
  82. X          if(pixel.y - aptr->pixel.y == CELL_HEIGHT && !cptr[0].depths[1])
  83. X        {
  84. X          if(!aptr->state)
  85. X            {
  86. X              aptr->state = 1;
  87. X              aptr->count = APPLE_ROCK_DELAY;
  88. X            }
  89. X        }
  90. X          else
  91. X        {
  92. X          aptr->state = 1;
  93. X          aptr->count = 1;
  94. X        }
  95. X        }
  96. X    }
  97. X      /*}}}*/
  98. X    }
  99. X  /*}}}*/
  100. X  /*{{{  redraw or blank prize?*/
  101. X  if(cherry && cherry->sprite)
  102. X    {
  103. X      SPRITE    *sptr;
  104. X      
  105. X      if(!nptr || cherry->sprite == SPRITE_DEN ||
  106. X      cherry->sprite == SPRITE_NORMAL + 2 ||
  107. X      (cherry->sprite != SPRITE_CHERRY && mptr->type != 4))
  108. X    {
  109. X      sptr = &sprites[cherry->sprite];
  110. X      if(display.background != COLOUR_ZERO)
  111. X        XCopyArea(display.display, sptr->mask, display.back, GCN(GC_MASK),
  112. X        0, 0, CELL_WIDTH, CELL_HEIGHT, pixel.x, pixel.y);
  113. X      XCopyArea(display.display, sptr->image, display.back, GCN(GC_OR),
  114. X          0, 0, CELL_WIDTH, CELL_HEIGHT, pixel.x, pixel.y);
  115. X    }
  116. X      else if(!knocked || cherry->sprite != SPRITE_CHERRY)
  117. X    {
  118. X      sptr = &sprites[SPRITE_CENTER_BASE +
  119. X          (cherry->sprite != SPRITE_CHERRY)];
  120. X      munch_back(0, 0, CELL_WIDTH, CELL_HEIGHT,
  121. X        pixel.x, pixel.y, sptr);
  122. X    }
  123. X    }
  124. X  /*}}}*/
  125. X  if(update.set)
  126. X    add_background(update.tl.x, update.tl.y,
  127. X    update.br.x - update.tl.x, update.br.y - update.tl.y);
  128. X  if(broke || nptr)
  129. X    global.broken = 1;
  130. X  assert(!nptr || nptr->visit);
  131. X  assert(mptr->cell.y >= 0 && mptr->cell.y < CELLS_DOWN &&
  132. X      mptr->cell.x >= 0 && mptr->cell.x < CELLS_ACROSS &&
  133. X      (mptr->cell.x || mptr->offset.x >= 0) &&
  134. X      (mptr->cell.y || mptr->offset.y >= 0) &&
  135. X      (mptr->cell.x < CELLS_ACROSS - 1 || mptr->offset.x <= 0) &&
  136. X      (mptr->cell.y < CELLS_DOWN - 1 || mptr->offset.y <= 0) &&
  137. X      (!mptr->offset.x || !mptr->offset.y));
  138. X  return nptr;
  139. }
  140. /*}}}*/
  141. /*{{{  void munch_back(sx, sy, width, height, dx, dy, sprite)*/
  142. static void munch_back FUNCARGLIST((sx, sy, width, height, dx, dy, sprite))
  143. int     sx      FUNCARGSEP
  144. int     sy      FUNCARGSEP
  145. int     width   FUNCARGSEP
  146. int     height  FUNCARGSEP
  147. int     dx      FUNCARGSEP
  148. int     dy      FUNCARGSEP
  149. SPRITE  *sprite FUNCARGTERM
  150. /*
  151. X * munches the background image with the specified sprite
  152. X */
  153. {
  154. X  if(display.background != COLOUR_ONE)
  155. X    XCopyArea(display.display, sprite->mask, display.back, GCN(GC_MASK),
  156. X    sx, sy, width, height, dx, dy);
  157. X  if(display.background != COLOUR_ZERO)
  158. X    XCopyArea(display.display, sprite->image, display.back, GCN(GC_BACK),
  159. X    sx, sy, width, height, dx, dy);
  160. X  bounding_box(dx, dy, width, height);
  161. X  return;
  162. }
  163. /*}}}*/
  164. /*{{{  void munch_hole(cptr, x, y)*/
  165. extern void munch_hole FUNCARGLIST((cptr, x, y))
  166. CELL      *cptr FUNCARGSEP
  167. int       x     FUNCARGSEP
  168. int       y     FUNCARGTERM
  169. /*
  170. X * cut out the background for a whole cell, and
  171. X * deal with connections to the adjoining cells
  172. X */
  173. {
  174. X  SPRITE    *sptr;
  175. X
  176. X
  177. X  /*{{{  cut out the center*/
  178. X  {
  179. X    sptr = &sprites[SPRITE_CENTER_BASE];
  180. X    munch_back(0, 0,
  181. X    CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  182. X    x, y,
  183. X    &sptr[!!(cptr[0].depths[0] || cptr[0].depths[2])]);
  184. X    munch_back(CELL_WIDTH >> 1, 0,
  185. X    CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  186. X    x + (CELL_WIDTH >> 1), y,
  187. X    &sptr[!!(cptr[0].depths[0] || cptr[0].depths[3])]);
  188. X    munch_back(CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  189. X    CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  190. X    x + (CELL_WIDTH >> 1), y + (CELL_HEIGHT >> 1),
  191. X    &sptr[!!(cptr[0].depths[1] || cptr[0].depths[3])]);
  192. X    munch_back(0, CELL_HEIGHT >> 1,
  193. X    CELL_WIDTH >> 1, CELL_HEIGHT >> 1,
  194. X    x, y + (CELL_HEIGHT >> 1),
  195. X    &sptr[!!(cptr[0].depths[1] || cptr[0].depths[2])]);
  196. X  }
  197. X  /*}}}*/
  198. X  sptr = &sprites[SPRITE_EDGE_BASE + 1];
  199. X  /*{{{  munch above?*/
  200. X  if(cptr[0].depths[0])
  201. X    {
  202. X      /*{{{  munch the left half of the edge above*/
  203. X      {
  204. X    unsigned  type;
  205. X        
  206. X    type = 0;
  207. X    if(cptr[0].depths[2])
  208. X      type = 2 * GAP_HEIGHT;
  209. X    if(cptr[-CELL_STRIDE].depths[2] < -VEL_X)
  210. X      type += GAP_HEIGHT;
  211. X    if(type == 3 * GAP_HEIGHT && (cptr[-1].depths[0] < -VEL_Y ||
  212. X        cptr[-CELL_STRIDE-1].depths[1] > VEL_Y))
  213. X      type = 4 * GAP_HEIGHT;
  214. X    munch_back(0, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  215. X        x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1), y - GAP_HEIGHT, sptr);
  216. X      }
  217. X      /*}}}*/
  218. X      /*{{{  munch the right half of the edge above*/
  219. X      {
  220. X    unsigned  type;
  221. X        
  222. X    type = 0;
  223. X    if(cptr[0].depths[3])
  224. X      type = 2 * GAP_HEIGHT;
  225. X    if(cptr[-CELL_STRIDE].depths[3] > VEL_X)
  226. X      type += GAP_HEIGHT;
  227. X    if(type == 3 * GAP_HEIGHT && (cptr[1].depths[0] < -VEL_Y ||
  228. X        cptr[-CELL_STRIDE+1].depths[1] > VEL_Y))
  229. X      type = 4 * GAP_HEIGHT;
  230. X    munch_back(EDGE_WIDTH >> 1, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  231. X        x + (CELL_WIDTH >> 1), y - GAP_HEIGHT, sptr);
  232. X      }
  233. X      /*}}}*/
  234. X    }
  235. X  /*}}}*/
  236. X  /*{{{  munch below?*/
  237. X  if(cptr[0].depths[1])
  238. X    {
  239. X      /*{{{  munch the left half of the edge below*/
  240. X      {
  241. X    unsigned  type;
  242. X        
  243. X    type = 0;
  244. X    if(cptr[0].depths[2])
  245. X      type = GAP_HEIGHT;
  246. X    if(cptr[CELL_STRIDE].depths[2] < -VEL_X)
  247. X      type += 2 * GAP_HEIGHT;
  248. X    if(type == 3 * GAP_HEIGHT && (cptr[-1].depths[1] > VEL_Y ||
  249. X        cptr[CELL_STRIDE-1].depths[0] < -VEL_Y))
  250. X      type = 4 * GAP_HEIGHT;
  251. X    munch_back(0, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  252. X        x + (CELL_WIDTH >> 1) - (EDGE_WIDTH >> 1),
  253. X        y + CELL_HEIGHT, sptr);
  254. X      }
  255. X      /*}}}*/
  256. X      /*{{{  munch the right half of the edge below*/
  257. X      {
  258. X    unsigned  type;
  259. X        
  260. X    type = 0;
  261. X    if(cptr[0].depths[3])
  262. X      type = GAP_HEIGHT;
  263. X    if(cptr[CELL_STRIDE].depths[3] > VEL_X)
  264. X      type += 2 * GAP_HEIGHT;
  265. X    if(type == 3 * GAP_HEIGHT &&
  266. X        (cptr[1].depths[1] > VEL_Y ||
  267. X        cptr[CELL_STRIDE+1].depths[0] < -VEL_Y))
  268. X      type = 4 * GAP_HEIGHT;
  269. X    munch_back(EDGE_WIDTH >> 1, type, EDGE_WIDTH >> 1, GAP_HEIGHT,
  270. X        x + (CELL_WIDTH >> 1), y + CELL_HEIGHT, sptr);
  271. X      }
  272. X      /*}}}*/
  273. X    }
  274. X  /*}}}*/
  275. X  sptr = &sprites[SPRITE_EDGE_BASE + 0];
  276. X  /*{{{  munch left?*/
  277. X  if(cptr[0].depths[2])
  278. X    {
  279. X      /*{{{  munch the top half of the edge left*/
  280. X      {
  281. X    unsigned  type;
  282. X        
  283. X    type = 0;
  284. X    if(cptr[0].depths[0])
  285. X      type = 2 * GAP_WIDTH;
  286. X    if(cptr[-1].depths[0] < -VEL_Y)
  287. X      type += GAP_WIDTH;
  288. X    if(type == 3 * GAP_WIDTH &&
  289. X        (cptr[-CELL_STRIDE].depths[2] < -VEL_X ||
  290. X        cptr[-CELL_STRIDE-1].depths[3] > VEL_X))
  291. X      type = 4 * GAP_WIDTH;
  292. X    munch_back(type, 0, GAP_HEIGHT, EDGE_HEIGHT >> 1,
  293. X        x - GAP_WIDTH, y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  294. X        sptr);
  295. X      }
  296. X      /*}}}*/
  297. X      /*{{{  munch the bottom half of the edge left*/
  298. X      {
  299. X    unsigned  type;
  300. X        
  301. X    type = 0;
  302. X    if(cptr[0].depths[1])
  303. X      type = 2 * GAP_WIDTH;
  304. X    if(cptr[-1].depths[1] > VEL_Y)
  305. X      type += GAP_WIDTH;
  306. X    if(type == 3 * GAP_WIDTH &&
  307. X        (cptr[CELL_STRIDE].depths[2] < -VEL_X ||
  308. X        cptr[CELL_STRIDE-1].depths[3] > VEL_X))
  309. X      type = 4 * GAP_WIDTH;
  310. X    munch_back(type, EDGE_HEIGHT >> 1, GAP_WIDTH, EDGE_HEIGHT >> 1,
  311. X        x - GAP_WIDTH, y + (CELL_HEIGHT >> 1), sptr);
  312. X      }
  313. X      /*}}}*/
  314. X    }
  315. X  /*}}}*/
  316. X  /*{{{  munch right?*/
  317. X  if(cptr[0].depths[3])
  318. X    {
  319. X      /*{{{  munch the top half of the edge right*/
  320. X      {
  321. X    unsigned  type;
  322. X        
  323. X    type = 0;
  324. X    if(cptr[0].depths[0])
  325. X      type = GAP_WIDTH;
  326. X    if(cptr[1].depths[0] < -VEL_Y)
  327. X      type += 2 * GAP_WIDTH;
  328. X    if(type == 3 * GAP_WIDTH &&
  329. X        (cptr[-CELL_STRIDE].depths[3] > VEL_X ||
  330. X        cptr[-CELL_STRIDE+1].depths[2] < -VEL_X))
  331. X      type = 4 * GAP_WIDTH;
  332. X    munch_back(type, 0, GAP_WIDTH, EDGE_HEIGHT >> 1,
  333. X        x + CELL_WIDTH, y + (CELL_HEIGHT >> 1) - (EDGE_HEIGHT >> 1),
  334. X        sptr);
  335. X      }
  336. X      /*}}}*/
  337. X      /*{{{  munch the bottom half of the edge right*/
  338. X      {
  339. X    unsigned  type;
  340. X        
  341. X    type = 0;
  342. X    if(cptr[0].depths[1])
  343. X      type = GAP_WIDTH;
  344. X    if(cptr[1].depths[1] > VEL_Y)
  345. X      type += 2 * GAP_WIDTH;
  346. X    if(type == 3 * GAP_WIDTH &&
  347. X        (cptr[CELL_STRIDE].depths[3] > VEL_X ||
  348. X        cptr[CELL_STRIDE+1].depths[2] < -VEL_X))
  349. X      type = 4 * GAP_WIDTH;
  350. X    munch_back(type, EDGE_HEIGHT >> 1, GAP_WIDTH, EDGE_HEIGHT >> 1,
  351. X        x + CELL_WIDTH, y + (CELL_HEIGHT >> 1), sptr);
  352. X      }
  353. X      /*}}}*/
  354. X    }
  355. X  /*}}}*/
  356. X  return;
  357. }
  358. /*}}}*/
  359. /*{{{  void new_face(mptr)*/
  360. extern void new_face FUNCARGLIST((mptr))
  361. MONSTER *mptr FUNCARGTERM
  362. /*
  363. X * calculates the required face for the direction,
  364. X * given the old face
  365. X */
  366. {
  367. X  int       dir;
  368. X  int       face;
  369. X
  370. X  if(mptr->push)
  371. X    dir = mptr->dir ^ 1;
  372. X  else
  373. X    dir = mptr->dir;
  374. X  face = mptr->face < 6 ? mptr->face : 2 + (mptr->face & 1);
  375. X  if(mptr->apple)
  376. X    mptr->face = 8 + (face > 2);
  377. X  else if(dir & 2)
  378. X    mptr->face = dir;
  379. X  else if(face == 2)
  380. X    mptr->face = dir;
  381. X  else if(face == 3)
  382. X    mptr->face = dir + 4;
  383. X  else if((dir ^ face) & 1)
  384. X    mptr->face ^= 5;
  385. X  if(mptr->face & 2 && mptr->pushing)
  386. X    mptr->face += 4;
  387. X  return;
  388. }
  389. /*}}}*/
  390. /*{{{  int valid_directions(mptr, cptr)*/
  391. extern int valid_directions FUNCARGLIST((mptr, cptr))
  392. MONSTER   *mptr FUNCARGSEP
  393. CELL      *cptr FUNCARGTERM
  394. /*
  395. X * sets the valid and nearer direction bits
  396. X * these are nr, nl, nd, nu, r, l, d, u
  397. X */
  398. {
  399. X  int       answer;
  400. X  int       offset;
  401. X
  402. X  answer = 0;
  403. X  if(offset = mptr->offset.y)
  404. X    /*{{{  up down only*/
  405. X    {
  406. X      if(offset > cptr->depths[0])
  407. X    answer |= 0x1;
  408. X      if(offset < cptr->depths[1])
  409. X    answer |= 0x2;
  410. X      if(offset < 0 ? cptr[0].distance < cptr[-CELL_STRIDE].distance :
  411. X      cptr[0].distance >= cptr[CELL_STRIDE].distance)
  412. X    answer |= 0x20;
  413. X      else
  414. X    answer |= 0x10;
  415. X    }
  416. X    /*}}}*/
  417. X  else if(offset = mptr->offset.x)
  418. X    /*{{{  left right only*/
  419. X    {
  420. X      if(offset > cptr->depths[2])
  421. X    answer |= 0x4;
  422. X      if(offset < cptr->depths[3])
  423. X    answer |= 0x8;
  424. X      if(offset < 0 ? cptr[0].distance < cptr[-1].distance :
  425. X      cptr[0].distance >= cptr[1].distance)
  426. X    answer |= 0x80;
  427. X      else
  428. X    answer |= 0x40;
  429. X    }
  430. X    /*}}}*/
  431. X  else
  432. X    /*{{{  at intersection*/
  433. X    {
  434. X      int       distance;
  435. X      
  436. X      if(cptr->depths[0])
  437. X    answer |= 0x1;
  438. X      if(cptr->depths[1])
  439. X    answer |= 0x2;
  440. X      if(cptr->depths[2])
  441. X    answer |= 0x4;
  442. X      if(cptr->depths[3])
  443. X    answer |= 0x8;
  444. X      distance = cptr->distance;
  445. X      if(distance > cptr[-CELL_STRIDE].distance)
  446. X    answer |= 0x10;
  447. X      if(distance > cptr[CELL_STRIDE].distance)
  448. X    answer |= 0x20;
  449. X      if(distance > cptr[-1].distance)
  450. X    answer |= 0x40;
  451. X      if(distance > cptr[1].distance)
  452. X    answer |= 0x80;
  453. X    }
  454. X    /*}}}*/
  455. X  answer &= answer << 4 | 0xF;
  456. X  return answer;
  457. }
  458. /*}}}*/
  459. SHAR_EOF
  460. echo 'File move.c is complete' &&
  461. chmod 0644 move.c ||
  462. echo 'restore of move.c failed'
  463. Wc_c="`wc -c < 'move.c'`"
  464. test 38428 -eq "$Wc_c" ||
  465.     echo 'move.c: original size 38428, current size' "$Wc_c"
  466. rm -f _shar_wnt_.tmp
  467. fi
  468. # ============= player.c ==============
  469. if test -f 'player.c' -a X"$1" != X"-c"; then
  470.     echo 'x - skipping player.c (File already exists)'
  471.     rm -f _shar_wnt_.tmp
  472. else
  473. > _shar_wnt_.tmp
  474. echo 'x - extracting player.c (Text)'
  475. sed 's/^X//' << 'SHAR_EOF' > 'player.c' &&
  476. /*{{{  (C) 1992 Nathan Sidwell*/
  477. /*****************************************************************************
  478. X            X M R I S V1.01
  479. X            ---------------
  480. X            (C) 1992 Nathan Sidwell
  481. X
  482. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  483. is in the public domain. Permission is granted to distribute and compile
  484. verbatim copies of this software for non-commercial, non-profit use,
  485. without fee. The software may be modified, provided that both the above copyright
  486. notice and this permission notice appear.
  487. X
  488. No guarantee is given as to the robustness or suitability of this
  489. software for your computer.
  490. X
  491. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  492. *****************************************************************************/
  493. /*}}}*/
  494. #include "xmris.h"
  495. /*{{{  void bounce_ball()*/
  496. extern void bounce_ball FUNCARGVOID
  497. /*
  498. X * throws, bounces, explodes & implodes the ball
  499. X * note that show_updates, does the ball ploting
  500. X */
  501. {
  502. X  switch(player.ball.state)
  503. X  {
  504. X    /*{{{  case 0: (held)*/
  505. X    case 0:
  506. X      if(player.throw == 1)
  507. X    {
  508. X      CELL      *cptr;
  509. X      unsigned  face;
  510. X    
  511. X      player.throw = 2;
  512. X      player.ball.state = 1;
  513. X      face = monster.list[0].face;
  514. X      player.ball.cell.x = monster.list[0].cell.x;
  515. X      player.ball.cell.y = monster.list[0].cell.y;
  516. X      player.ball.offset.x = monster.list[0].offset.x + ball_throw[face].x;
  517. X      player.ball.offset.y = monster.list[0].offset.y + ball_throw[face].y;
  518. X      player.ball.count = ball_dir[face];
  519. X      cptr = BOARDCELL(player.ball.cell.x, player.ball.cell.y);
  520. X      switch(monster.list[0].dir)
  521. X      {
  522. X        /*{{{  case 0: (up)*/
  523. X        case 0:
  524. X          if(player.ball.offset.y > -(CELL_HEIGHT / 2))
  525. X        /*EMPTY*/;
  526. X          else if(cptr[-CELL_STRIDE].visit)
  527. X        {
  528. X          player.ball.offset.y += CELL_HEIGHT + GAP_HEIGHT;
  529. X          player.ball.cell.y--;
  530. X        }
  531. X          else if(cptr[-CELL_STRIDE * 2].depths[1] - player.ball.offset.y >
  532. X          CELL_HEIGHT / 2 + CELL_HEIGHT + GAP_HEIGHT)
  533. X        {
  534. X          player.ball.offset.y += (CELL_HEIGHT + GAP_HEIGHT) * 2;
  535. X          player.ball.cell.y -= 2;
  536. X        }
  537. X          else if(player.ball.offset.y + CELL_HEIGHT / 2 <
  538. X          cptr[0].depths[0])
  539. X        player.ball.state = 0;
  540. X          break;
  541. X        /*}}}*/
  542. X        /*{{{  case 1: (down)*/
  543. X        case 1:
  544. X          if(player.ball.offset.y < (CELL_HEIGHT / 2))
  545. X        /*EMPTY*/;
  546. X          else if(cptr[CELL_STRIDE].visit)
  547. X        {
  548. X          player.ball.offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  549. X          player.ball.cell.y++;
  550. X        }
  551. X          else if(player.ball.offset.y - cptr[CELL_STRIDE * 2].depths[0] >
  552. X          CELL_HEIGHT / 2 + CELL_HEIGHT + GAP_HEIGHT)
  553. X        {
  554. X          player.ball.offset.y -= (CELL_HEIGHT + GAP_HEIGHT) * 2;
  555. X          player.ball.cell.y += 2;
  556. X        }
  557. X          else if(player.ball.offset.y - CELL_HEIGHT / 2 >
  558. X          cptr[0].depths[1])
  559. X        player.ball.state = 0;
  560. X          break;
  561. X        /*}}}*/
  562. X        /*{{{  case 2: (left)*/
  563. X        case 2:
  564. X          if(player.ball.offset.x > -(CELL_WIDTH / 2))
  565. X        /*EMPTY*/;
  566. X          else if(cptr[-1].visit)
  567. X        {
  568. X          player.ball.offset.x += CELL_WIDTH + GAP_WIDTH;
  569. X          player.ball.cell.x--;
  570. X        }
  571. X          else if(cptr[-2].depths[3] - player.ball.offset.x >
  572. X          CELL_WIDTH / 2 + CELL_WIDTH + GAP_WIDTH)
  573. X        {
  574. X          player.ball.offset.x += (CELL_WIDTH + GAP_WIDTH) * 2;
  575. X          player.ball.cell.x -= 2;
  576. X        }
  577. X          else if(player.ball.offset.x + CELL_WIDTH / 2 <
  578. X          cptr[0].depths[2])
  579. X        player.ball.state = 0;
  580. X          break;
  581. X        /*}}}*/
  582. X        /*{{{  case 3: (right)*/
  583. X        case 3:
  584. X          if(player.ball.offset.x < (CELL_HEIGHT / 2))
  585. X        /*EMPTY*/;
  586. X          else if(cptr[1].visit)
  587. X        {
  588. X          player.ball.offset.x -= CELL_WIDTH + GAP_WIDTH;
  589. X          player.ball.cell.x++;
  590. X        }
  591. X          else if(player.ball.offset.x - cptr[2].depths[2] >
  592. X          CELL_WIDTH / 2 + CELL_WIDTH + GAP_WIDTH)
  593. X        {
  594. X          player.ball.offset.x -= (CELL_WIDTH + GAP_WIDTH) * 2;
  595. X          player.ball.cell.x += 2;
  596. X        }
  597. X          else if(player.ball.offset.x - CELL_HEIGHT / 2 >
  598. X          cptr[0].depths[3])
  599. X        player.ball.state = 0;
  600. X          break;
  601. X        /*}}}*/
  602. X      }
  603. X      player.ball.pixel.x =
  604. X          PIXELX(player.ball.cell.x, player.ball.offset.x) + CELL_WIDTH / 2;
  605. X      player.ball.pixel.y =
  606. X          PIXELY(player.ball.cell.y, player.ball.offset.y) + CELL_HEIGHT / 2;
  607. X    }
  608. X      break;
  609. X    /*}}}*/
  610. X    /*{{{  case 1: (bounce)*/
  611. X    case 1:
  612. X    {
  613. X      int       i;
  614. X      CELL      *cptr;
  615. X    
  616. X      cptr = BOARDCELL(player.ball.cell.x, player.ball.cell.y);
  617. X      for(i = BALL_STEPS; i--;)
  618. X    {
  619. X      int       walls;
  620. X      /* bit vector tl, br, bl, tr, t, b, l, r */
  621. X    
  622. X      /*{{{  moved to above or below cell?*/
  623. X      if(player.ball.offset.y > CELL_HEIGHT / 2 &&
  624. X          cptr[CELL_STRIDE].depths[0])
  625. X        {
  626. X          player.ball.offset.y -= CELL_HEIGHT + GAP_HEIGHT;
  627. X          player.ball.cell.y++;
  628. X          cptr += CELL_STRIDE;
  629. X        }
  630. X      else if(player.ball.offset.y < -CELL_HEIGHT / 2 &&
  631. X          cptr[-CELL_STRIDE].depths[1])
  632. X        {
  633. X          player.ball.offset.y += CELL_HEIGHT + GAP_HEIGHT;
  634. X          player.ball.cell.y--;
  635. X          cptr -= CELL_STRIDE;
  636. X        }
  637. X      /*}}}*/
  638. X      /*{{{  moved to left or right cell?*/
  639. X      if(player.ball.offset.x > CELL_WIDTH / 2 && cptr[1].depths[2])
  640. X        {
  641. X          player.ball.offset.x -= CELL_WIDTH + GAP_WIDTH;
  642. X          player.ball.cell.x++;
  643. X          cptr++;
  644. X        }
  645. X      else if(player.ball.offset.x < -CELL_WIDTH / 2 && cptr[-1].depths[3])
  646. X        {
  647. X          player.ball.offset.x += CELL_WIDTH + GAP_WIDTH;
  648. X          player.ball.cell.x--;
  649. X          cptr--;
  650. X        }
  651. X      /*}}}*/
  652. X      walls = 0x00;
  653. X      /*{{{  set the maze walls*/
  654. X      {
  655. X        unsigned  quadrant;
  656. X        /* quadrants to, bo, lo, ro, ti, bi, li, ri, t, b, l, r */
  657. X            
  658. X        /* work out where we are in the cell */
  659. X        quadrant = 0x000;
  660. X        /*{{{  y place*/
  661. X        if(player.ball.offset.y < -CELL_HEIGHT / 2 - VEL_Y)
  662. X          quadrant |= 0x008;
  663. X        else if(player.ball.offset.y < -CELL_HEIGHT / 2)
  664. X          quadrant |= 0x800;
  665. X        else if(player.ball.offset.y < -CELL_HEIGHT / 2 + VEL_Y)
  666. X          quadrant |= 0x080;
  667. X        else if(player.ball.offset.y >= CELL_HEIGHT / 2 + VEL_Y)
  668. X          quadrant |= 0x004;
  669. X        else if(player.ball.offset.y >= CELL_HEIGHT / 2)
  670. X          quadrant |= 0x400;
  671. X        else if(player.ball.offset.y >= CELL_HEIGHT / 2 - VEL_Y)
  672. X          quadrant |= 0x040;
  673. X        /*}}}*/
  674. X        /*{{{  x place*/
  675. X        if(player.ball.offset.x < -CELL_WIDTH / 2 - VEL_X)
  676. X          quadrant |= 0x002;
  677. X        else if(player.ball.offset.x < -CELL_WIDTH / 2)
  678. X          quadrant |= 0x200;
  679. X        else if(player.ball.offset.x < -CELL_WIDTH / 2 + VEL_X)
  680. X          quadrant |= 0x020;
  681. X        else if(player.ball.offset.x >= CELL_WIDTH / 2 + VEL_X)
  682. X          quadrant |= 0x001;
  683. X        else if(player.ball.offset.x >= CELL_WIDTH / 2)
  684. X          quadrant |= 0x100;
  685. X        else if(player.ball.offset.x >= CELL_WIDTH / 2 - VEL_X)
  686. X          quadrant |= 0x010;
  687. X        /*}}}*/
  688. X        if(quadrant & 0x888)
  689. X          /*{{{  above cell*/
  690. X          {
  691. X        if(player.ball.offset.y <=
  692. X            cptr[0].depths[0] - CELL_HEIGHT / 2 + VEL_Y)
  693. X          walls |= 0x98;
  694. X        if(quadrant & 0x808)
  695. X          {
  696. X            unsigned  mask;
  697. X                  
  698. X            if(quadrant & 0x800)
  699. X              mask = 0x93;
  700. X            else
  701. X              mask = 0xF3;
  702. X            if(quadrant & 0x020)
  703. X              walls |= mask & 0xA2;
  704. X            if(quadrant & 0x010)
  705. X              walls |= mask & 0x51;
  706. X          }
  707. X        else
  708. X          {
  709. X            if(quadrant & 0x020)
  710. X              {
  711. X            if(cptr[0].depths[0] >= -VEL_Y ||
  712. X                cptr[0].depths[2] >= -VEL_X ||
  713. X                cptr[-1].depths[0] >= -VEL_Y ||
  714. X                cptr[-CELL_STRIDE].depths[2] >= -VEL_X)
  715. X              walls |= 0x80;
  716. X              }
  717. X            else if(quadrant & 0x010)
  718. X              {
  719. X            if(cptr[0].depths[0] >= -VEL_Y ||
  720. X                cptr[0].depths[3] <= VEL_X ||
  721. X                cptr[1].depths[0] >= -VEL_Y ||
  722. X                cptr[-CELL_STRIDE].depths[3] <= VEL_X)
  723. X              walls |= 0x10;
  724. X              }
  725. X          }
  726. X          }
  727. X          /*}}}*/
  728. X        else if(quadrant & 0x444)
  729. X          /*{{{  below cell*/
  730. X          {
  731. X        if(player.ball.offset.y >=
  732. X            cptr[0].depths[1] + CELL_HEIGHT / 2 - VEL_Y)
  733. X          walls |= 0x64;
  734. X        if(quadrant & 0x404)
  735. X          {
  736. X            unsigned  mask;
  737. X                  
  738. X            if(quadrant & 0x400)
  739. X              mask = 0x63;
  740. X            else
  741. X              mask = 0xF3;
  742. X            if(quadrant & 0x020)
  743. X              walls |= mask & 0xA2;
  744. X            if(quadrant & 0x010)
  745. X              walls |= mask & 0x51;
  746. X          }
  747. X        else
  748. X          {
  749. X            if(quadrant & 0x020)
  750. X              {
  751. X            if(cptr[0].depths[1] <= VEL_Y ||
  752. X                cptr[0].depths[2] >= -VEL_X ||
  753. X                cptr[-1].depths[1] <= VEL_Y ||
  754. X                cptr[CELL_STRIDE].depths[2] >= -VEL_X)
  755. X              walls |= 0x20;
  756. X              }
  757. X            else if(quadrant & 0x010)
  758. X              {
  759. X            if(cptr[0].depths[1] <= VEL_Y ||
  760. X                cptr[0].depths[3] <= VEL_X ||
  761. X                cptr[1].depths[1] <= VEL_Y ||
  762. X                cptr[CELL_STRIDE].depths[3] <= VEL_X)
  763. X              walls |= 0x40;
  764. X              }
  765. X          }
  766. X          }
  767. X          /*}}}*/
  768. X        if(quadrant & 0x222)
  769. X          /*{{{  left cell*/
  770. X          {
  771. X        if(player.ball.offset.x <=
  772. X            cptr[0].depths[2] - CELL_WIDTH / 2 + VEL_X)
  773. X          walls |= 0xA2;
  774. X        if(quadrant & 0x202)
  775. X          {
  776. X            unsigned  mask;
  777. X                  
  778. X            if(quadrant & 0x200)
  779. X              mask = 0xAC;
  780. X            else
  781. X              mask = 0xFC;
  782. X            if(quadrant & 0x080)
  783. X              walls |= mask & 0x98;
  784. X            if(quadrant & 0x040)
  785. X              walls |= mask & 0x64;
  786. X          }
  787. X          }
  788. X          /*}}}*/
  789. X        else if(quadrant & 0x111)
  790. X          /*{{{  right cell*/
  791. X          {
  792. X        if(player.ball.offset.x >=
  793. X            cptr[0].depths[3] + CELL_WIDTH / 2 - VEL_X)
  794. X          walls |= 0x51;
  795. X        if(quadrant & 0x101)
  796. X          {
  797. X            unsigned  mask;
  798. X                  
  799. X            if(quadrant & 0x100)
  800. X              mask = 0x5C;
  801. X            else
  802. X              mask = 0xFC;
  803. X            if(quadrant & 0x080)
  804. X              walls |= mask & 0x98;
  805. X            if(quadrant & 0x040)
  806. X              walls |= mask & 0x64;
  807. X          }
  808. X          }
  809. X          /*}}}*/
  810. X      }
  811. X      /*}}}*/
  812. X      /*{{{  set apple walls*/
  813. X      {
  814. X        unsigned  i;
  815. X        APPLE     *aptr;
  816. X            
  817. X        for(aptr = apple.list, i = apple.apples; i--; aptr++)
  818. X          {
  819. X        int     x, y;
  820. X        int     edge;
  821. X        /* edge ot, ob, ol, or, t, b, l, r */
  822. X              
  823. X        if(aptr->state < 4)
  824. X          {
  825. X            x = aptr->pixel.x;
  826. X            y = aptr->pixel.y;
  827. X            edge = 0;
  828. X            /*{{{  Y edge*/
  829. X            if(player.ball.pixel.y - y < -VEL_Y ||
  830. X            player.ball.pixel.y - y >= CELL_HEIGHT + VEL_Y)
  831. X              /*EMPTY*/;
  832. X            else if(player.ball.pixel.y - y < 0)
  833. X              edge |= 0X80;
  834. X            else if(player.ball.pixel.y - y < CELL_HEIGHT / 2)
  835. X              edge |= 0X08;
  836. X            else if(player.ball.pixel.y - y < CELL_HEIGHT)
  837. X              edge |= 0x04;
  838. X            else
  839. X              edge |= 0x40;
  840. X            /*}}}*/
  841. X            /*{{{  X edge*/
  842. X            if(player.ball.pixel.x - x < -VEL_X ||
  843. X            player.ball.pixel.x - x >= CELL_WIDTH + VEL_X)
  844. X              /*EMPTY*/;
  845. X            else if(player.ball.pixel.x - x < 0)
  846. X              edge |= 0X20;
  847. X            else if(player.ball.pixel.x - x < CELL_WIDTH / 2)
  848. X              edge |= 0X02;
  849. X            else if(player.ball.pixel.x - x < CELL_WIDTH)
  850. X              edge |= 0x01;
  851. X            else
  852. X              edge |= 0x10;
  853. X            /*}}}*/
  854. X            if(edge)
  855. X              {
  856. X            /*{{{  top*/
  857. X            if(edge & 0X88 && edge & 0X33)
  858. X              {
  859. X                if(edge & 0X03)
  860. X                  walls |= 0X04;
  861. X                if(edge & 0X23)
  862. X                  walls |= 0X40;
  863. X                if(walls & 0X13)
  864. X                  walls |= 0X20;
  865. X              }
  866. X            /*}}}*/
  867. X            /*{{{  bottom*/
  868. X            if(edge & 0X44 && edge & 0X33)
  869. X              {
  870. X                if(edge & 0X03)
  871. X                  walls |= 0X08;
  872. X                if(edge & 0X23)
  873. X                  walls |= 0X10;
  874. X                if(walls & 0X13)
  875. X                  walls |= 0X80;
  876. X              }
  877. X            /*}}}*/
  878. X            /*{{{  left*/
  879. X            if(edge & 0X22 && edge & 0X0C)
  880. X              {
  881. X                walls |= 0X01;
  882. X                if(edge & 0X8C)
  883. X                  walls |= 0X40;
  884. X                if(walls & 0X4C)
  885. X                  walls |= 0X10;
  886. X              }
  887. X            /*}}}*/
  888. X            /*{{{  right*/
  889. X            if(edge & 0X11 && edge & 0X0C)
  890. X              {
  891. X                walls |= 0X02;
  892. X                if(edge & 0X8C)
  893. X                  walls |= 0X20;
  894. X                if(walls & 0X4C)
  895. X                  walls |= 0X80;
  896. X              }
  897. X            /*}}}*/
  898. X              }
  899. X          }
  900. X          }
  901. X      }
  902. X      /*}}}*/
  903. X      if((walls & 0xC) == 0xC || (walls & 0x03) == 0x03)
  904. X        {
  905. X          player.ball.state = 2;
  906. X          player.ball.count = 0;
  907. X          break;
  908. X        }
  909. X      else
  910. X        {
  911. X          /*{{{  bounce?*/
  912. X          switch(player.ball.count)
  913. X          {
  914. X        /*{{{  case 0: (up left)*/
  915. X        case 0:
  916. X          if(!(walls & 0X80))
  917. X            /*EMPTY*/;
  918. X          else if((walls & 0X0A) == 0X08)
  919. X            player.ball.count = 2;
  920. X          else if((walls & 0X0A) == 0X02)
  921. X            player.ball.count = 3;
  922. X          else
  923. X            player.ball.count = 1;
  924. X          break;
  925. X        /*}}}*/
  926. X        /*{{{  case 1: (down right)*/
  927. X        case 1:
  928. X          if(!(walls & 0X40))
  929. X            /*EMPTY*/;
  930. X          else if((walls & 0X05) == 0X04)
  931. X            player.ball.count = 3;
  932. X          else if((walls & 0X05) == 0X01)
  933. X            player.ball.count = 2;
  934. X          else
  935. X            player.ball.count = 0;
  936. X          break;
  937. X        /*}}}*/
  938. X        /*{{{  case 2: (down left)*/
  939. X        case 2:
  940. X          if(!(walls & 0X20))
  941. X            /*EMPTY*/;
  942. X          else if((walls & 0X06) == 0X04)
  943. X            player.ball.count = 0;
  944. X          else if((walls & 0X06) == 0X02)
  945. X            player.ball.count = 1;
  946. X          else
  947. X            player.ball.count = 3;
  948. X          break;
  949. X        /*}}}*/
  950. X        /*{{{  case 3: (up right)*/
  951. X        case 3:
  952. X          if(!(walls & 0X10))
  953. X            /*EMPTY*/;
  954. X          else if((walls & 0X09) == 0X08)
  955. X            player.ball.count = 1;
  956. X          else if((walls & 0X09) == 0X01)
  957. X            player.ball.count = 0;
  958. X          else
  959. X            player.ball.count = 2;
  960. X          break;
  961. X        /*}}}*/
  962. X          }
  963. X          /*}}}*/
  964. X          /*{{{  move ball*/
  965. X          switch(player.ball.count)
  966. X          {
  967. X        /*{{{  case 0: (up left)*/
  968. X        case 0:
  969. X          player.ball.offset.x -= VEL_X;
  970. X          player.ball.offset.y -= VEL_Y;
  971. X          player.ball.pixel.x -= VEL_X;
  972. X          player.ball.pixel.y -= VEL_Y;
  973. X          break;
  974. X        /*}}}*/
  975. X        /*{{{  case 1: (down right)*/
  976. X        case 1:
  977. X          player.ball.offset.x += VEL_X;
  978. X          player.ball.offset.y += VEL_Y;
  979. X          player.ball.pixel.x += VEL_X;
  980. X          player.ball.pixel.y += VEL_Y;
  981. X          break;
  982. X        /*}}}*/
  983. X        /*{{{  case 2: (down left)*/
  984. X        case 2:
  985. X          player.ball.offset.x -= VEL_X;
  986. X          player.ball.offset.y += VEL_Y;
  987. X          player.ball.pixel.x -= VEL_X;
  988. X          player.ball.pixel.y += VEL_Y;
  989. X          break;
  990. X        /*}}}*/
  991. X        /*{{{  case 3: (up right)*/
  992. X        case 3:
  993. X          player.ball.offset.x += VEL_X;
  994. X          player.ball.offset.y -= VEL_Y;
  995. X          player.ball.pixel.x += VEL_X;
  996. X          player.ball.pixel.y -= VEL_Y;
  997. X          break;
  998. X        /*}}}*/
  999. X          }
  1000. X          /*}}}*/
  1001. X        }
  1002. X    }
  1003. X      if(player.ball.state == 1)
  1004. X    /*{{{  hit a monster?*/
  1005. X    {
  1006. X      unsigned  i;
  1007. X      MONSTER   *mptr;
  1008. X        
  1009. X      for(mptr = monster.list, i = monster.monsters; i--; mptr++)
  1010. X        if(!mptr->shot && !mptr->apple &&
  1011. X        player.ball.pixel.x - mptr->pixel.x >= 0 &&
  1012. X        player.ball.pixel.x - mptr->pixel.x < CELL_WIDTH &&
  1013. X        player.ball.pixel.y - mptr->pixel.y >= 0 &&
  1014. X        player.ball.pixel.y - mptr->pixel.y < CELL_HEIGHT)
  1015. X          {
  1016. X        if(mptr == monster.list)
  1017. X          {
  1018. X            player.ball.state = 0;
  1019. X            player.ball.count = monster.list[0].face;
  1020. X            player.ball.pixel.x = monster.list[0].pixel.x +
  1021. X            CELL_WIDTH / 2;
  1022. X            player.ball.pixel.y = monster.list[0].pixel.y +
  1023. X            CELL_HEIGHT / 2;
  1024. X          }
  1025. X        else
  1026. X          {
  1027. X            mptr->shot = 1;
  1028. X            player.ball.state = 2;
  1029. X            player.ball.count = 0;
  1030. X          }
  1031. X        break;
  1032. X          }
  1033. X    }
  1034. X    /*}}}*/
  1035. X      break;
  1036. X    }
  1037. X    /*}}}*/
  1038. X    /*{{{  case 2: (explode)*/
  1039. X    case 2:
  1040. X      player.ball.count++;
  1041. X      if(player.ball.count == BALL_EXPLODE)
  1042. X    player.ball.state = 3;
  1043. X      break;
  1044. X    /*}}}*/
  1045. X    /*{{{  case 3: (exploded)*/
  1046. X    case 3:
  1047. X      if(random() < 4)
  1048. X    {
  1049. X      player.ball.state = 4;
  1050. X      player.ball.count--;
  1051. X    }
  1052. X      break;
  1053. X    /*}}}*/
  1054. X    /*{{{  case 4: (implode)*/
  1055. X    case 4:
  1056. X    {
  1057. X      int       face;
  1058. X      
  1059. X      player.ball.count--;
  1060. X      face = monster.list[0].face;
  1061. X      player.ball.pixel.x = monster.list[0].pixel.x + CELL_WIDTH / 2;
  1062. X      player.ball.pixel.y = monster.list[0].pixel.y + CELL_HEIGHT / 2;
  1063. X      if(!player.ball.count)
  1064. X    player.ball.state = 0;
  1065. X      break;
  1066. X    }
  1067. X    /*}}}*/
  1068. X  }
  1069. X  if(!player.ball.state)
  1070. X    {
  1071. X      player.ball.count = monster.list[0].face;
  1072. X      player.ball.image = monster.list[0].image;
  1073. X      player.ball.pixel.x = monster.list[0].pixel.x + CELL_WIDTH / 2;
  1074. X      player.ball.pixel.y = monster.list[0].pixel.y + CELL_HEIGHT / 2;
  1075. X    }
  1076. X  return;
  1077. }
  1078. /*}}}*/
  1079. /*{{{  void move_player()*/
  1080. extern void move_player FUNCARGVOID
  1081. /*
  1082. X * moves the player
  1083. X * and deals with eating cherries etc
  1084. X */
  1085. {
  1086. X  CELL      *cptr;
  1087. X  unsigned  dir;
  1088. X
  1089. X  dir = monster.list[0].dir;
  1090. X  /*{{{  motionevent?*/
  1091. X  if(player.motionevent && !player.keyboard &&
  1092. X      (!monster.list[0].stop ||
  1093. X       player.raw_mouse.x - player.mouse.x * (CELL_WIDTH + GAP_WIDTH) >
  1094. X      BORDER_LEFT + GAP_WIDTH / 2 + (CELL_WIDTH + GAP_WIDTH) / 4 +
  1095. X      CELL_WIDTH + GAP_WIDTH ||
  1096. X       player.raw_mouse.y - (int)player.mouse.y * (CELL_HEIGHT + GAP_HEIGHT) >
  1097. X      BORDER_TOP + GAP_HEIGHT / 2 + (CELL_HEIGHT + GAP_HEIGHT) / 4 +
  1098. X      CELL_HEIGHT + GAP_HEIGHT ||
  1099. X       player.raw_mouse.x - (int)player.mouse.x * (CELL_WIDTH + GAP_WIDTH) <
  1100. X      BORDER_LEFT + GAP_WIDTH / 2 - (GAP_WIDTH + CELL_WIDTH) / 4||
  1101. X       player.raw_mouse.y - (int)player.mouse.y * (CELL_HEIGHT + GAP_HEIGHT) <
  1102. X      BORDER_TOP + GAP_HEIGHT / 2 - (GAP_HEIGHT + CELL_HEIGHT) / 4))
  1103. X    /*
  1104. X     * for mouse motion, we get the cell number for the mouse, and
  1105. X     * set dir & mouse dir to point towards it
  1106. X     */
  1107. X    {
  1108. X      int       x, y;
  1109. X    
  1110. X      x = (player.raw_mouse.x - BORDER_LEFT - GAP_WIDTH / 2) /
  1111. X      (GAP_WIDTH + CELL_WIDTH);
  1112. X      y = (player.raw_mouse.y - BORDER_TOP - GAP_HEIGHT / 2) /
  1113. X      (GAP_HEIGHT + CELL_HEIGHT);
  1114. X      /*{{{  clip x*/
  1115. X      if(x < 0)
  1116. X    x = 0;
  1117. X      else if(x > CELLS_ACROSS - 1)
  1118. X    x = CELLS_ACROSS - 1;
  1119. X      /*}}}*/
  1120. X      /*{{{  clip y*/
  1121. X      if(y < 0)
  1122. X    y = 0;
  1123. X      else if(y > CELLS_DOWN - 1)
  1124. X    y = CELLS_DOWN - 1;
  1125. X      /*}}}*/
  1126. X      if(y != player.mouse.y || x != player.mouse.x)
  1127. X    {
  1128. X      unsigned  dir;
  1129. X      unsigned  second;
  1130. X    
  1131. X      player.mouse.x = x;
  1132. X      player.mouse.y = y;
  1133. X      /*{{{  calc x direction*/
  1134. X      if(x == monster.list[0].cell.x && !monster.list[0].offset.x)
  1135. X        x = 0;
  1136. X      else if(x < monster.list[0].cell.x ||
  1137. X          (x == monster.list[0].cell.x && monster.list[0].offset.x > 0))
  1138. X        x = 6;
  1139. X      else
  1140. X        x = 7;
  1141. X      /*}}}*/
  1142. X      /*{{{  calc y direction*/
  1143. X      if(y == monster.list[0].cell.y && !monster.list[0].offset.y)
  1144. X        y = 0;
  1145. X      else if(y < monster.list[0].cell.y ||
  1146. X          (y == monster.list[0].cell.y && monster.list[0].offset.y > 0))
  1147. X        y = 4;
  1148. X      else
  1149. X        y = 5;
  1150. X      /*}}}*/
  1151. X      /*{{{  select which way round to do them*/
  1152. X      if(monster.list[0].dir & 2)
  1153. X        {
  1154. X          if(monster.list[0].dir != x)
  1155. X        {
  1156. X          dir = y;
  1157. X          second = x;
  1158. X        }
  1159. X          else
  1160. X        {
  1161. X          dir = x;
  1162. X          second = y;
  1163. X        }
  1164. X        }
  1165. X      else
  1166. X        {
  1167. X          if(monster.list[0].dir != y)
  1168. X        {
  1169. X          dir = x;
  1170. X          second = y;
  1171. X        }
  1172. X          else
  1173. X        {
  1174. X          dir = y;
  1175. X          second = x;
  1176. X        }
  1177. X        }
  1178. X      /*}}}*/
  1179. X      player.next_dir = 0;
  1180. X      /*{{{  do u turn fiddling*/
  1181. X      if(!dir)
  1182. X        dir = second;
  1183. X      else if(!second)
  1184. X        second = dir;
  1185. X      else if(monster.list[0].offset.x && !(dir & 2))
  1186. X        {
  1187. X          player.next_dir = dir;
  1188. X          if(monster.list[0].offset.x < -(CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  1189. X        dir = 6;
  1190. X          else if(monster.list[0].offset.x > (CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  1191. X        dir = 7;
  1192. X          else if(monster.list[0].offset.x > 0 &&
  1193. X          monster.list[0].offset.x <= (CELL_WIDTH + GAP_WIDTH) / 4)
  1194. X        dir = 6;
  1195. X          else if(monster.list[0].offset.x < 0 &&
  1196. X          monster.list[0].offset.x >= -(CELL_WIDTH + GAP_WIDTH) / 4)
  1197. X        dir = 7;
  1198. X          else
  1199. X        dir = monster.list[0].dir | 4;
  1200. X        }
  1201. X      else if(monster.list[0].offset.y && (dir & 2))
  1202. X        {
  1203. X          player.next_dir = dir;
  1204. X          if(monster.list[0].offset.y < -(CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  1205. X        dir = 4;
  1206. X          else if(monster.list[0].offset.y > (CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  1207. X        dir = 5;
  1208. X          else if(monster.list[0].offset.y > 0 &&
  1209. X          monster.list[0].offset.y <= (CELL_HEIGHT + GAP_HEIGHT) / 4)
  1210. X        dir = 4;
  1211. X          else if(monster.list[0].offset.y < 0 &&
  1212. X          monster.list[0].offset.y >= -(CELL_HEIGHT + GAP_HEIGHT) / 4)
  1213. X        dir = 5;
  1214. X          else
  1215. X        dir = monster.list[0].dir | 4;
  1216. X        }
  1217. X      /*}}}*/
  1218. X      monster.list[0].dir = dir & 3;
  1219. X      monster.list[0].stop = !(dir & 4);
  1220. X      player.mouse_dir = second;
  1221. X    }
  1222. X    }
  1223. X  /*}}}*/
  1224. X  /*{{{  key change?*/
  1225. X  if(player.bashed || (player.old_pressed ^ player.pressed) & 0xF)
  1226. X  /*
  1227. X   * The keys have changed, so we need to select a new direction
  1228. X   * if we're not an interchange to change dir, we keep going
  1229. X   * in the current direction, if that is non-zero,
  1230. X   * else we go to the nearest interchange
  1231. X   */
  1232. X  {
  1233. X    unsigned  valid;
  1234. X    unsigned  pressed;
  1235. X    
  1236. X    player.mouse_dir = 0;
  1237. X    pressed = player.pressed & ~player.bashed;
  1238. X    if(!pressed)
  1239. X      pressed = player.pressed;
  1240. X    valid = 0xF;
  1241. X    /*{{{  work out valid direction and the edges*/
  1242. X    if(monster.list[0].offset.x)
  1243. X      {
  1244. X    valid &= 0xC;
  1245. X    if(!monster.list[0].cell.y)
  1246. X      pressed &= 0xE;
  1247. X    else if(monster.list[0].cell.y == CELLS_DOWN - 1)
  1248. X      pressed &= 0xD;
  1249. X      }
  1250. X    else if(monster.list[0].offset.y)
  1251. X      {
  1252. X    valid &= 0x3;
  1253. X    if(!monster.list[0].cell.x)
  1254. X      pressed &= 0xB;
  1255. X    else if(monster.list[0].cell.x == CELLS_ACROSS - 1)
  1256. X      pressed &= 0x7;
  1257. X      }
  1258. X    else
  1259. X      {
  1260. X    if(!monster.list[0].cell.x)
  1261. X      valid &= 0xB;
  1262. X    else if(monster.list[0].cell.x == CELLS_ACROSS - 1)
  1263. X      valid &= 0x7;
  1264. X    if(!monster.list[0].cell.y)
  1265. X      valid &= 0xE;
  1266. X    else if(monster.list[0].cell.y == CELLS_DOWN - 1)
  1267. X      valid &= 0xD;
  1268. X    pressed &= valid;
  1269. X      }
  1270. X    /*}}}*/
  1271. X    if((pressed & 0x3) == 0x3)
  1272. X      pressed &= 0xC;
  1273. X    if((pressed & 0xC) == 0xC)
  1274. X      pressed &= 0x3;
  1275. X    if(!pressed)
  1276. X      {
  1277. X    monster.list[0].stop = 1;
  1278. X    player.next_dir = 0;
  1279. X      }
  1280. X    else if((valid & pressed) == pressed)
  1281. X      {
  1282. X    unsigned  dir;
  1283. X    
  1284. X    if((pressed & 0x3) && (pressed & 0xC))
  1285. X      pressed &= monster.list[0].dir & 2 ? 0x3 : 0xC;
  1286. X    for(dir = 0; !(pressed & 1); dir++, pressed >>= 1)
  1287. X      /*EMPTY*/;
  1288. X    player.next_dir = 0;
  1289. X    monster.list[0].dir = dir;
  1290. X    monster.list[0].stop = 0;
  1291. X      }
  1292. X    else
  1293. X      {
  1294. X    unsigned  dir;
  1295. X    
  1296. X    pressed &= ~valid;
  1297. X    for(dir = 0; !(pressed & 1); pressed >>= 1)
  1298. X      dir++;
  1299. X    player.next_dir = dir | 4;
  1300. X    if(monster.list[0].stop)
  1301. X      {
  1302. X        /*{{{  select nearest cell*/
  1303. X        if(dir & 2)
  1304. X          {
  1305. X        if(monster.list[0].offset.y <
  1306. X            -(CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  1307. X          dir = 0;
  1308. X        else if(monster.list[0].offset.y >
  1309. X            (CELL_HEIGHT + GAP_HEIGHT) * 3 / 4)
  1310. X          dir = 1;
  1311. X        else if(monster.list[0].offset.y > 0 &&
  1312. X            monster.list[0].offset.y <=
  1313. X            (CELL_HEIGHT + GAP_HEIGHT) / 4)
  1314. X          dir = 0;
  1315. X        else if(monster.list[0].offset.y < 0 &&
  1316. X            monster.list[0].offset.y >=
  1317. X            -(CELL_HEIGHT + GAP_HEIGHT) / 4)
  1318. X          dir = 1;
  1319. X        else
  1320. X          dir = monster.list[0].dir;
  1321. X          }
  1322. X        else
  1323. X          {
  1324. X        if(monster.list[0].offset.x <
  1325. X            -(CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  1326. X          dir = 2;
  1327. X        else if(monster.list[0].offset.x >
  1328. X            (CELL_WIDTH + GAP_WIDTH) * 3 / 4)
  1329. X          dir = 3;
  1330. X        else if(monster.list[0].offset.x > 0 &&
  1331. X            monster.list[0].offset.x <=
  1332. X            (CELL_WIDTH + GAP_WIDTH) / 4)
  1333. X          dir = 2;
  1334. X        else if(monster.list[0].offset.x < 0 &&
  1335. X            monster.list[0].offset.x >=
  1336. X            -(CELL_WIDTH + GAP_WIDTH) / 4)
  1337. X          dir = 3;
  1338. X        else
  1339. X          dir = monster.list[0].dir;
  1340. X          }
  1341. X        /*}}}*/
  1342. X        monster.list[0].dir = dir;
  1343. X        monster.list[0].stop = 0;
  1344. X      }
  1345. X      }
  1346. X    if(monster.list[0].stop)
  1347. X      player.bashed = 0;
  1348. X    else if(player.bashed == 0x10)
  1349. X      player.bashed = 0;
  1350. X    else if(player.bashed & (1 << monster.list[0].dir))
  1351. X      player.bashed = 0;
  1352. X    else if(!(player.bashed & (3 << (monster.list[0].dir & 2))))
  1353. X      player.bashed = 0x10;
  1354. X  }
  1355. X  /*}}}*/
  1356. X  player.old_pressed = player.pressed;
  1357. X  if(player.throw == 2)
  1358. X    {
  1359. X      if(!player.button)
  1360. X    player.throw = 0;
  1361. X    }
  1362. X  else if(player.throw == 0)
  1363. X    player.throw = player.button;
  1364. X  if(dir != monster.list[0].dir)
  1365. X    new_face(&monster.list[0]);
  1366. X  if(monster.list[0].pause)
  1367. X    {
  1368. X      player.cherry = player.distance = 0;
  1369. X      monster.list[0].pause = 0;
  1370. X    }
  1371. X  else if(!monster.list[0].stop)
  1372. X    {
  1373. X      if(!monster.list[0].cycle)
  1374. X    {
  1375. X      monster.list[0].cycle = MONSTER_CYCLES;
  1376. X      monster.list[0].image++;
  1377. X      if(monster.list[0].image == MONSTER_IMAGES)
  1378. X        monster.list[0].image = 0;
  1379. X      
  1380. X    }
  1381. X      monster.list[0].cycle--;
  1382. X      cptr = move_muncher(&monster.list[0]);
  1383. X      /*{{{  pushing?*/
  1384. X      {
  1385. X    unsigned  push;
  1386. X        
  1387. X    push = monster.list[0].pause && (monster.list[0].dir & 2);
  1388. X    if(push != monster.list[0].pushing)
  1389. X      {
  1390. X        monster.list[0].pushing = push;
  1391. X        new_face(&monster.list[0]);
  1392. X      }
  1393. X      }
  1394. X      /*}}}*/
  1395. X      if(monster.list[0].stop)
  1396. X    {
  1397. X      monster.list[0].pause = 0;
  1398. X      player.bashed = 1 << monster.list[0].dir;
  1399. X    }
  1400. X      if(cptr)
  1401. X    {
  1402. X      if(cptr->sprite == SPRITE_CHERRY)
  1403. X        /*{{{  eat cherry*/
  1404. X        {
  1405. X          cptr->sprite = 0;
  1406. X          global.cherries--;
  1407. X          add_score(50, 0, 0);
  1408. X          player.cherry++;
  1409. X          if(player.cherry == 8)
  1410. X        {
  1411. X          add_score(500,
  1412. X              monster.list[0].pixel.x + CELL_WIDTH / 2,
  1413. X              monster.list[0].pixel.y + CELL_HEIGHT / 2);
  1414. X          player.cherry = 0;
  1415. X        }
  1416. X          else
  1417. X        player.distance =
  1418. X            (CELL_WIDTH + GAP_WIDTH) / VEL_X;
  1419. X        }
  1420. X        /*}}}*/
  1421. X      else if(cptr->sprite >= SPRITE_PRIZE_BASE &&
  1422. X          cptr->sprite < SPRITE_PRIZE_BASE + SPRITE_PRIZES)
  1423. X        /*{{{  eat prize*/
  1424. X        {
  1425. X          int     score;
  1426. X            
  1427. X          history.prize |= 1;
  1428. X          cptr->sprite = 0;
  1429. X          score = player.screen * 500 + 500;
  1430. X          add_score(score > 9500 ? 9500 : score,
  1431. X          monster.list[0].pixel.x + CELL_WIDTH / 2,
  1432. X          monster.list[0].pixel.y + CELL_HEIGHT / 2);
  1433. X          global.state = 2;
  1434. X          if(!extra.escape)
  1435. X        extra_escape();
  1436. X          monster.den = 3;
  1437. X          monster.delay = 1;
  1438. X        }
  1439. X        /*}}}*/
  1440. X    }
  1441. X    }
  1442. X  if(player.distance)
  1443. X    player.distance--;
  1444. X  else
  1445. X    player.cherry = 0;
  1446. X  /*{{{  player looping*/
  1447. X  if(monster.list[0].stop ||
  1448. X      monster.list[0].offset.x || monster.list[0].offset.y)
  1449. X    /*EMPTY*/;
  1450. X  else if(player.mouse_dir &&
  1451. X      monster.list[0].cell.x == player.mouse.x &&
  1452. X      monster.list[0].cell.y == player.mouse.y)
  1453. X    {
  1454. X      player.next_dir = player.mouse_dir = 0;
  1455. X      monster.list[0].stop = 1;
  1456. X    }
  1457. X  else if(player.mouse_dir &&
  1458. X      monster.list[0].dir != (player.mouse_dir & 3) &&
  1459. X      (monster.list[0].cell.x == player.mouse.x ||
  1460. X       monster.list[0].cell.y == player.mouse.y))
  1461. X    {
  1462. X      monster.list[0].dir = player.mouse_dir & 3;
  1463. X      player.next_dir = 0;
  1464. X      new_face(&monster.list[0]);
  1465. X    }
  1466. X  else if((!monster.list[0].cell.x && monster.list[0].dir == 2) ||
  1467. X      (!monster.list[0].cell.y && monster.list[0].dir == 0) ||
  1468. X      (monster.list[0].cell.x == CELLS_ACROSS - 1 &&
  1469. X      monster.list[0].dir == 3) ||
  1470. X      (monster.list[0].cell.y == CELLS_DOWN - 1 &&
  1471. X      monster.list[0].dir == 1))
  1472. X    {
  1473. X      player.next_dir = 0;
  1474. X      monster.list[0].stop = 1;
  1475. X      player.bashed = 1 << monster.list[0].dir;
  1476. X    }
  1477. X  else if(player.next_dir)
  1478. X    {
  1479. X      monster.list[0].dir = player.next_dir & 3;
  1480. X      player.next_dir = 0;
  1481. X      new_face(&monster.list[0]);
  1482. X    }
  1483. X  /*}}}*/
  1484. X  if(!monster.list[0].shot)
  1485. X    /*{{{  hit monster?*/
  1486. X    {
  1487. X      unsigned  i;
  1488. X      MONSTER   *mptr;
  1489. X      int       x, y;
  1490. X    
  1491. X      x = monster.list[0].pixel.x - CELL_WIDTH + GAP_WIDTH;
  1492. X      y = monster.list[0].pixel.y - CELL_HEIGHT + GAP_HEIGHT;
  1493. X      for(mptr = &monster.list[1], i = monster.monsters - 1; i--; mptr++)
  1494. X    if(!mptr->chew && !mptr->shot && !mptr->apple &&
  1495. X        mptr->pixel.x - x > 0 &&
  1496. X        mptr->pixel.x - x < 2 * (CELL_WIDTH - GAP_WIDTH) &&
  1497. X        mptr->pixel.y - y > 0 &&
  1498. X        mptr->pixel.y - y < 2 * (CELL_HEIGHT - GAP_HEIGHT))
  1499. X      {
  1500. X        monster.list[0].shot = 1;
  1501. X        break;
  1502. X      }
  1503. X    }
  1504. X    /*}}}*/
  1505. X  return;
  1506. }
  1507. /*}}}*/
  1508. SHAR_EOF
  1509. chmod 0644 player.c ||
  1510. echo 'restore of player.c failed'
  1511. Wc_c="`wc -c < 'player.c'`"
  1512. test 26545 -eq "$Wc_c" ||
  1513.     echo 'player.c: original size 26545, current size' "$Wc_c"
  1514. rm -f _shar_wnt_.tmp
  1515. fi
  1516. # ============= timer.c ==============
  1517. if test -f 'timer.c' -a X"$1" != X"-c"; then
  1518.     echo 'x - skipping timer.c (File already exists)'
  1519.     rm -f _shar_wnt_.tmp
  1520. else
  1521. > _shar_wnt_.tmp
  1522. echo 'x - extracting timer.c (Text)'
  1523. sed 's/^X//' << 'SHAR_EOF' > 'timer.c' &&
  1524. /*{{{  (C) 1992 Nathan Sidwell*/
  1525. /*****************************************************************************
  1526. X            X M R I S V1.01
  1527. X            ---------------
  1528. X            (C) 1992 Nathan Sidwell
  1529. X
  1530. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  1531. is in the public domain. Permission is granted to distribute and compile
  1532. verbatim copies of this software for non-commercial, non-profit use,
  1533. without fee. The software may be modified, provided that both the above copyright
  1534. notice and this permission notice appear.
  1535. X
  1536. No guarantee is given as to the robustness or suitability of this
  1537. software for your computer.
  1538. X
  1539. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  1540. *****************************************************************************/
  1541. /*}}}*/
  1542. #include "xmris.h"
  1543. #include <time.h>
  1544. #include <sys/time.h>
  1545. #include <signal.h>
  1546. /*{{{  timer*/
  1547. static struct
  1548. {
  1549. X  void      (*handler)();   /* original handler */
  1550. X  unsigned  mask;           /* previous signal mask */
  1551. X  unsigned  volatile counter;        /* timer counter */
  1552. X  struct itimerval interval; /* interval time */
  1553. } timer;
  1554. /*}}}*/
  1555. /*{{{  prototypes*/
  1556. static void timer_alarm PROTOARGLIST((int));
  1557. /*}}}*/
  1558. /*{{{  void timer_alarm(sig)*/
  1559. static void timer_alarm FUNCARGLIST((sig))
  1560. int       sig FUNCARGTERM
  1561. {
  1562. X  timer.counter = 1;
  1563. X  signal(SIGALRM, timer_alarm);
  1564. X  return;
  1565. }
  1566. /*}}}*/
  1567. /*{{{  void timer_close()*/
  1568. extern void timer_close FUNCARGVOID
  1569. /*
  1570. X * closes the timer stuff
  1571. X */
  1572. {
  1573. X  signal(SIGALRM, timer.handler);
  1574. X  return;
  1575. }
  1576. /*}}}*/
  1577. /*{{{  void timer_open()*/
  1578. extern void timer_open FUNCARGVOID
  1579. /*
  1580. X * initialize the timer stuff
  1581. X * this means installing the alarm signam handler
  1582. X */
  1583. {
  1584. X  timer.interval.it_interval.tv_sec = 0;
  1585. X  timer.interval.it_interval.tv_usec = 0;
  1586. X  timer.interval.it_value.tv_sec = 0;
  1587. X  timer.interval.it_value.tv_usec = 0;
  1588. X  timer.handler = signal(SIGALRM, timer_alarm);
  1589. X  return;
  1590. }
  1591. /*}}}*/
  1592. /*{{{  void timer_start(tick)*/
  1593. extern void timer_start FUNCARGLIST((tick))
  1594. unsigned  long tick FUNCARGTERM
  1595. /*
  1596. X * starts an interval timer
  1597. X * which ticks every n microseconds
  1598. X */
  1599. {
  1600. X  timer.interval.it_value.tv_usec = tick;
  1601. X  timer.counter = 1;
  1602. X  timer_wait();
  1603. X  return;
  1604. }
  1605. /*}}}*/
  1606. /*{{{  void timer_stop()*/
  1607. extern void timer_stop FUNCARGVOID
  1608. /*
  1609. X * stops the interval timer
  1610. X */
  1611. {
  1612. X  timer.interval.it_value.tv_usec = 0;
  1613. X  timer_wait();
  1614. X  XDrawLine(display.display, display.window, GCN(GC_BALL),
  1615. X      WINDOW_WIDTH - global.missed, WINDOW_HEIGHT - 1,
  1616. X      WINDOW_WIDTH, WINDOW_HEIGHT - 1);
  1617. X  global.missed = 0;
  1618. X  return;
  1619. }
  1620. /*}}}*/
  1621. /*{{{  void timer_wait()*/
  1622. extern void timer_wait FUNCARGVOID
  1623. /*
  1624. X * waits for the next timer interrupt
  1625. X * if this has already gone by, then we immediatley return
  1626. X */
  1627. {
  1628. X  if(!timer.counter)
  1629. X    {
  1630. X      int     mask;
  1631. X      
  1632. X      mask = sigblock(sigmask(SIGALRM));
  1633. X      if(!timer.counter)
  1634. X    {
  1635. X      if(global.missed)
  1636. X        {
  1637. X          XDrawPoint(display.display, display.window, GCN(GC_BALL),
  1638. X          WINDOW_WIDTH - global.missed, WINDOW_HEIGHT - 1);
  1639. X          global.missed--;
  1640. X        }
  1641. X      sigpause(0);
  1642. X    }
  1643. X      sigsetmask(mask);
  1644. X    }
  1645. X  else if(global.missed < WINDOW_WIDTH)
  1646. X    {
  1647. X      global.missed++;
  1648. X      XDrawPoint(display.display, display.window, GCN(GC_BALL),
  1649. X      WINDOW_WIDTH - global.missed, WINDOW_HEIGHT - 1);
  1650. X    }
  1651. X  timer.counter = 0;
  1652. X  setitimer(ITIMER_REAL, &timer.interval, (struct itimerval *)NULL);
  1653. X  return;
  1654. }
  1655. /*}}}*/
  1656. SHAR_EOF
  1657. chmod 0644 timer.c ||
  1658. echo 'restore of timer.c failed'
  1659. Wc_c="`wc -c < 'timer.c'`"
  1660. test 3360 -eq "$Wc_c" ||
  1661.     echo 'timer.c: original size 3360, current size' "$Wc_c"
  1662. rm -f _shar_wnt_.tmp
  1663. fi
  1664. # ============= xmris.c ==============
  1665. if test -f 'xmris.c' -a X"$1" != X"-c"; then
  1666.     echo 'x - skipping xmris.c (File already exists)'
  1667.     rm -f _shar_wnt_.tmp
  1668. else
  1669. > _shar_wnt_.tmp
  1670. echo 'x - extracting xmris.c (Text)'
  1671. sed 's/^X//' << 'SHAR_EOF' > 'xmris.c' &&
  1672. /*{{{  (C) 1992 Nathan Sidwell*/
  1673. /*****************************************************************************
  1674. X            X M R I S V1.01
  1675. X            ---------------
  1676. X            (C) 1992 Nathan Sidwell
  1677. X
  1678. This program is copyright (C) 1992 Nathan Sidwell. This software and documentation
  1679. is in the public domain. Permission is granted to distribute and compile
  1680. verbatim copies of this software for non-commercial, non-profit use,
  1681. without fee. The software may be modified, provided that both the above copyright
  1682. notice and this permission notice appear.
  1683. X
  1684. No guarantee is given as to the robustness or suitability of this
  1685. software for your computer.
  1686. X
  1687. Nathan Sidwell  INMOS UK |                 | nathan@inmos.co.uk       DoD#0390
  1688. *****************************************************************************/
  1689. /*}}}*/
  1690. #include "xmris.h"
  1691. #include <time.h>
  1692. /*{{{  prototypes*/
  1693. static void age_scores PROTOARGLIST((void));
  1694. static void parse_args PROTOARGLIST((int, char **));
  1695. /*}}}*/
  1696. /*{{{  void add_score(increment, x, y)*/
  1697. extern void add_score FUNCARGLIST((points, x, y))
  1698. int       points  FUNCARGSEP
  1699. int       x       FUNCARGSEP
  1700. int       y       FUNCARGTERM
  1701. /*
  1702. X * adds the given score (which may be zero)
  1703. X * and displays it at the top of the screen
  1704. X * if the coordinate > 0 then add the score into the onboard list
  1705. X */
  1706. {
  1707. X  player.score += points;
  1708. X  /*{{{  text score*/
  1709. X  {
  1710. X    unsigned  length;
  1711. X    char      text[10];
  1712. X    int       ascent, descent;
  1713. X    int       direction;
  1714. X    XCharStruct chars;
  1715. X    int       x, y;
  1716. X    
  1717. X    length = itoa(text, player.score, 0);
  1718. X    XQueryTextExtents(display.display, font.font, text, length,
  1719. X    &direction, &ascent, &descent, &chars);
  1720. X    x = BORDER_LEFT + (CELL_WIDTH + GAP_WIDTH) * 4 -
  1721. X    CELL_WIDTH / 2 - chars.width;
  1722. X    y = (CELL_HEIGHT - ascent - descent) / 2 + ascent +
  1723. X    BORDER_TOP - CELL_HEIGHT;
  1724. X    XDrawImageString(display.display, display.back, GCN(GC_TEXT),
  1725. X    x, y, text, length);
  1726. X    add_background(x, y - ascent, chars.width, ascent + descent);
  1727. X  }
  1728. X  /*}}}*/
  1729. X  /*{{{  board score?*/
  1730. X  if(y)
  1731. X    {
  1732. X      unsigned  length;
  1733. X      char      text[10];
  1734. X      int       i;
  1735. X      SCORE     *sptr;
  1736. X      SPRITE    *dptr;
  1737. X    
  1738. X      dptr = &sprites[SPRITE_DIGITS];
  1739. X      length = itoa(text, points, 0);
  1740. X      /*{{{  remove oldest score?*/
  1741. X      if(update.score.scores == BOARD_SCORES)
  1742. X    {
  1743. X      add_background(update.score.list[0].place.x,
  1744. X          update.score.list[0].place.y,
  1745. X          DIGIT_WIDTH * 4, DIGIT_HEIGHT);
  1746. X      update.score.scores--;
  1747. X      memmove(&update.score.list[0], &update.score.list[1],
  1748. X          sizeof(SCORE) * update.score.scores);
  1749. X    }
  1750. X      /*}}}*/
  1751. X      sptr = &update.score.list[update.score.scores++];
  1752. X      sptr->count = SCORE_SHOW;
  1753. X      sptr->place.x = x - DIGIT_WIDTH * 2;
  1754. X      sptr->place.y = y - DIGIT_HEIGHT / 2;
  1755. X      /*{{{  centering*/
  1756. X      if(length != 4)
  1757. X    {
  1758. X      x = (4 - length) * (DIGIT_WIDTH / 2);
  1759. X      XCopyArea(display.display, dptr->image, sptr->image, GCN(GC_COPY),
  1760. X          10 * DIGIT_WIDTH, 0, x, DIGIT_HEIGHT, 0, 0);
  1761. X      XCopyArea(display.display, dptr->image, sptr->image, GCN(GC_COPY),
  1762. X          10 * DIGIT_WIDTH, 0, x, DIGIT_HEIGHT, 4 * DIGIT_WIDTH - x, 0);
  1763. X      XCopyArea(display.display, dptr->mask, sptr->mask, GCN(GC_COPY),
  1764. X          10 * DIGIT_WIDTH, 0, x, DIGIT_HEIGHT, 0, 0);
  1765. X      XCopyArea(display.display, dptr->mask, sptr->mask, GCN(GC_COPY),
  1766. X          10 * DIGIT_WIDTH, 0, x, DIGIT_HEIGHT, 4 * DIGIT_WIDTH - x, 0);
  1767. X    }
  1768. X      else
  1769. X    x = 0;
  1770. X      /*}}}*/
  1771. X      for(i = 0; i < length; i++, x += DIGIT_WIDTH)
  1772. X    {
  1773. X      XCopyArea(display.display, dptr->image, sptr->image, GCN(GC_COPY),
  1774. X          (text[i] - '0') * DIGIT_WIDTH, 0, DIGIT_WIDTH, DIGIT_HEIGHT,
  1775. X          x, 0);
  1776. X      XCopyArea(display.display, dptr->mask, sptr->mask, GCN(GC_COPY),
  1777. X          (text[i] - '0') * DIGIT_WIDTH, 0, DIGIT_WIDTH, DIGIT_HEIGHT,
  1778. X          x, 0);
  1779. X    }
  1780. X    }
  1781. X  /*}}}*/
  1782. X  return;
  1783. }
  1784. /*}}}*/
  1785. /*{{{  void age_scores()*/
  1786. static void age_scores FUNCARGVOID
  1787. /*
  1788. X * ages the onboard scores, and removes the old ones
  1789. X */
  1790. {
  1791. X  SCORE     *sptr;
  1792. X  int       i;
  1793. X
  1794. X  for(sptr = update.score.list, i = update.score.scores; i--; sptr++)
  1795. X    if(!sptr->count--)
  1796. X      {
  1797. X    Pixmap    image, mask;
  1798. X    
  1799. X    add_background(sptr->place.x, sptr->place.y,
  1800. X        DIGIT_WIDTH * 4, DIGIT_HEIGHT);
  1801. X    mask = sptr->mask;
  1802. X    image = sptr->image;
  1803. X    memmove(sptr, sptr + 1, i * sizeof(SCORE));
  1804. X    sptr[i].mask = mask;
  1805. X    sptr[i].image = image;
  1806. X    update.score.scores--;
  1807. X    sptr--;
  1808. X     }
  1809. X  return;
  1810. }
  1811. /*}}}*/
  1812. /*{{{  void calc_distances()*/
  1813. extern void calc_distances FUNCARGVOID
  1814. /*
  1815. X * sets the distances from each cell to the player
  1816. X * this is so the monsters have non-local knowlegde
  1817. X * increment the non-zero cells
  1818. X * this proceeds as a sort of flood fill operation, starting
  1819. X * from the player's cell and moving outwards
  1820. X */
  1821. {
  1822. X  CELL    **aptr, **sptr;
  1823. X  CELL    *list[2][FLOOD_FILL];
  1824. X  CELL    *cptr;
  1825. X  int     toggle;
  1826. X  int     x, y;
  1827. X  int     count;
  1828. X
  1829. X  global.broken = 0;
  1830. X  for(y = CELLS_DOWN; y--;)
  1831. X    {
  1832. X      cptr = BOARDCELL(0, y);
  1833. X      for(x = CELLS_ACROSS; x--; cptr++)
  1834. X    cptr->distance = cptr->visit ? 0 : 255;
  1835. X    }
  1836. X  toggle = 0;
  1837. X  cptr = BOARDCELL(monster.list[0].cell.x, monster.list[0].cell.y);
  1838. X  cptr->distance = count = 1;
  1839. X  list[0][0] = cptr;
  1840. X  list[0][1] = NULL;
  1841. X  while(list[toggle][0])
  1842. X  {
  1843. X    sptr = list[toggle];
  1844. X    toggle = !toggle;
  1845. X    aptr = list[toggle];
  1846. X    count++;
  1847. X    while(cptr = *sptr++)
  1848. X      {
  1849. X    CELL      *tptr;
  1850. X    
  1851. X    /*{{{  go up?*/
  1852. X    if(cptr->depths[0])
  1853. X      {
  1854. X        tptr = cptr - CELL_STRIDE;
  1855. X        if(tptr->visit && !tptr->distance)
  1856. X          {
  1857. X        tptr->distance = count;
  1858. X        *aptr++ = tptr;
  1859. X          }
  1860. X      }
  1861. X    /*}}}*/
  1862. X    /*{{{  go down?*/
  1863. X    if(cptr->depths[1])
  1864. X      {
  1865. X        tptr = cptr + CELL_STRIDE;
  1866. X        if(tptr->visit && !tptr->distance)
  1867. X          {
  1868. X        tptr->distance = count;
  1869. X        *aptr++ = tptr;
  1870. X          }
  1871. X      }
  1872. X    /*}}}*/
  1873. X    /*{{{  go left?*/
  1874. X    if(cptr->depths[2])
  1875. X      {
  1876. X        tptr = cptr - 1;
  1877. X        if(tptr->visit && !tptr->distance)
  1878. X          {
  1879. X        tptr->distance = count;
  1880. X        *aptr++ = tptr;
  1881. SHAR_EOF
  1882. true || echo 'restore of xmris.c failed'
  1883. fi
  1884. echo 'End of  part 5'
  1885. echo 'File xmris.c is continued in part 6'
  1886. echo 6 > _shar_seq_.tmp
  1887. exit 0
  1888. -- 
  1889. ---
  1890. Senior Systems Scientist        mail: dcmartin@msi.com
  1891. Molecular Simulations, Inc.        uucp: uunet!dcmartin
  1892. 796 North Pastoria Avenue        at&t: 408/522-9236
  1893.