home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Games / WormWars / Source / system.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-09  |  89.0 KB  |  3,070 lines

  1. /* $Filename:        WormWars/Source/system.c $
  2.  * $VER:            Worm Wars 4.4 $
  3.  * $Description:    API calls for Amiga $
  4.  *
  5.  * © Copyright 1999 James R. Jacobs. Freely distributable.
  6.  *        _
  7.  *       //        -=AMIGA=-
  8.  *      //
  9.  * _   //
  10.  * \\ //
  11.  *  \X/
  12.  *
  13.  * Release version.
  14.  
  15. #INCLUDES -------------------------------------------------------------- */
  16.  
  17. #include "system.h"                // #includes everything else
  18.  
  19. // GLOBAL VARIABLES (owned by engine.c, imported by amiga.lib) ------------
  20.  
  21. AGLOBAL    struct Library*            TimerBase                        = NULL;
  22.  
  23. // EXTERNAL VARIABLES (owned by engine.c, imported by system.c) -----------
  24.  
  25. IMPORT    struct Library*            SysBase;
  26.  
  27. IMPORT    ABOOL                    clearthem, modified;
  28. IMPORT    SBYTE                    a, board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  29.                                 brush, eachworm[4][2][9],
  30.                                 field[FIELDX + 1][FIELDY + 1],
  31.                                 hi, level, levels, lo,
  32.                                 startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
  33. IMPORT    STRPTR                    pathname;
  34. IMPORT    SWORD                    secondsleft, secondsperlevel;
  35. IMPORT    ULONG                    delay, r;
  36. IMPORT    struct HiScoreStruct    hiscore[HISCORES + 1];
  37. IMPORT    struct TeleportStruct    teleport[MAXLEVELS + 1][4];
  38. IMPORT    struct WormStruct        worm[4];
  39.  
  40. // MODULE VARIABLES (used only within system.c) ---------------------------
  41.  
  42. MODULE    struct ASLBase*            ASLBase                            = NULL;
  43. MODULE    struct GadToolsBase*    GadToolsBase                    = NULL;
  44. MODULE    struct GfxBase*            GfxBase                            = NULL;
  45. MODULE    struct IntuitionBase*    IntuitionBase                    = NULL;
  46. MODULE    struct MEDPlayerBase*    MEDPlayerBase                    = NULL;
  47.  
  48. MODULE    struct RDArgs*            ArgsPtr                            = NULL;
  49. MODULE    struct FileRequester*    ASLRqPtr                        = NULL;
  50. MODULE    ABOOL                    AudioClosed                        = TRUE;
  51. MODULE    struct MsgPort*            AudioPortPtr[4]                    = {NULL, NULL, NULL, NULL};
  52. MODULE    struct IOAudio*            AudioRqPtr[4]                    = {NULL, NULL, NULL, NULL};
  53. MODULE    struct Gadget*            CheckboxGadgetPtr                = NULL;
  54. MODULE    SBYTE                    Controller                        = GPCT_NOCONTROLLER;
  55. MODULE    struct timeval*            CurrentValPtr                    = NULL;
  56. MODULE    struct Gadget*            CycleGadgetPtr[4]                = {NULL, NULL, NULL, NULL};
  57. MODULE    ABOOL                    eversent[4];
  58. MODULE    UBYTE*                    fbase                            = NULL;
  59. MODULE    ULONG                    fsize;
  60. MODULE    BPTR                    FilePtr                            = NULL;
  61. MODULE    SBYTE                    fxable = 2, musicable = 2;
  62. MODULE    struct InputEvent        GameEvent;
  63. MODULE    struct Gadget*            GListPtr                        = NULL;
  64. MODULE    ABOOL                    ignore                            = FALSE;
  65. MODULE    SBYTE                    InputClosed                        = TRUE;
  66. MODULE    struct MsgPort*          InputPortPtr                    = NULL;
  67. MODULE    struct IOStdReq*        InputRqPtr                        = NULL;
  68. MODULE    ABOOL                    iso                                = TRUE;
  69. MODULE    ABOOL                    joy                                = FALSE;
  70. MODULE    SBYTE                    JoyClosed                        = TRUE;
  71. MODULE    struct MsgPort*            JoyPortPtr                        = NULL;
  72. MODULE    struct IOStdReq*        JoyRqPtr                        = NULL;
  73. MODULE    ULONG                    length[SAMPLES + 1][2];
  74. MODULE    struct Window*            MainWindowPtr                    = NULL;
  75. MODULE    struct Menu*            MenuPtr                            = NULL;
  76. MODULE    SBYTE                    mode                            = FALSE;
  77. MODULE    SBYTE                    OldPri                            = 0;
  78. MODULE    APTR                    OldWindowPtr                    = NULL;
  79. MODULE    struct timeval*            PausedValPtr                    = NULL;
  80. MODULE    SWORD                    pixy;
  81. MODULE    struct Gadget*            PrevGadgetPtr                    = NULL;
  82. MODULE    struct Process*            ProcessPtr                        = NULL;
  83. MODULE    ULONG                    receipter[4]                    = {(ULONG) -1, (ULONG) -1, (ULONG) -1, (ULONG) -1};
  84. MODULE    UBYTE*                    sbase[SAMPLES + 1];
  85. MODULE    struct Screen*            ScreenPtr                        = NULL;
  86. MODULE    struct MMD0*            SongPtr                            = NULL;
  87. MODULE    ULONG                    speed[SAMPLES + 1];
  88. MODULE    ULONG                    ssize[SAMPLES + 1];
  89. MODULE    struct timeval*            StartValPtr                        = NULL;
  90. MODULE    ABOOL                    sticky                            = FALSE;
  91. MODULE    struct Gadget*            StringGadgetPtr[6]                = {NULL, NULL, NULL, NULL, NULL};
  92. MODULE    SBYTE                    TimerClosed                        = TRUE;
  93. MODULE    struct MsgPort*            TimerPortPtr                    = NULL;
  94. MODULE    struct timerequest*        TimerRqPtr                        = NULL;
  95. MODULE    struct VisualInfo*        VisualInfoPtr                    = NULL;
  96. MODULE    ULONG                    yes[SAMPLES + 1];
  97. MODULE    struct TextAttr            Topaz8 =
  98. {    (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
  99. };
  100.  
  101. // FUNCTIONS --------------------------------------------------------------
  102.  
  103. int main(int argc, char** argv)
  104. {
  105. ABOOL                argument                = FALSE,
  106.                     success                    = FALSE,
  107.                     rememberiso;
  108. SBYTE                player, which;
  109. TEXT                saystring[SAYLIMIT + 1];
  110. UWORD                Pens[10]                = {BLACK, WHITE, WHITE, WHITE, DARKGREY, PURPLE, BLACK, BLACK, BLUE, (UWORD) ~0};
  111. SLONG                args[5]                    = {0L, 0L, 0L, 0L, 0L};
  112. struct ColorSpec    Colours[21] =
  113. {   /* colour   red     green   blue    description */
  114.     {   0,      0x0,    0x0,    0x0},   //        BLACK
  115.     {   1,      0xF,    0xF,    0xF},   //        WHITE
  116.     {   2,      0x2,    0x2,    0x2},   //    DARKGREY
  117.     {   3,      0x6,    0x6,    0x6},   // medium grey
  118.     {   4,      0xA,    0xA,    0xA},   //   LIGHTGREY
  119.     {   5,      0x0,    0x0,    0x0},   //        black
  120.     {   6,      0xA,    0x2,    0xA},   //        PURPLE
  121.     {   7,      0x8,    0x4,    0x2},   //        brown
  122.     {   8,      0x3,    0x9,    0x3},   //    DARKGREEN
  123.     {   9,      0x4,    0xE,    0x4},   //  light GREEN
  124.     {   10,     0xF,    0x1,    0x1},   //    DARKRED
  125.     {   11,     0xF,    0x4,    0x4},   //  light RED
  126.     {   12,     0x3,    0x3,    0xF},   //    DARKBLUE
  127.     {   13,     0x6,    0x6,    0xF},   //  light BLUE
  128.     {   14,     0xA,    0x8,    0x3},   //    DARKYELLOW
  129.     {   15,     0xC,    0xC,    0x2},   //  light YELLOW
  130.     {   16,     0x0,    0x0,    0x0},   // pointer: transparent
  131.     {   17,     0xE,    0x4,    0x4},   // pointer: fill
  132.     {   18,     0x3,    0x3,    0x3},   // pointer: shadow
  133.     {   19,     0xC,    0xC,    0xC},   // pointer: shine
  134.     {   -1,     NULL,   NULL,   NULL
  135. }   };
  136.  
  137. /* Start of program.
  138.  
  139. version embedding into executable */
  140.  
  141. if (0) // that is, never
  142.     say(VERSION, ANYTHING);
  143.  
  144. if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37L)))
  145. {    Write(Output(), OLDKICKSTART, strlen(OLDKICKSTART));
  146.     cleanexit(EXIT_FAILURE);
  147. }
  148.  
  149. // From this point onwards, we can be sure we have Kickstart 2.04+...
  150.  
  151. for (which = 0; which <= SAMPLES; which++)
  152.     sbase[which] = NULL;
  153.  
  154. ProcessPtr = (struct Process *) FindTask(NULL);
  155.  
  156. // argument parsing
  157.  
  158. if (!(ArgsPtr = ReadArgs("-F=NOFX/S,-M=NOMUSIC/S,-P=PRI/K/N,-O=OVERHEAD/S,FILE", args, NULL)))
  159. {    Printf("Usage: %s [-f=NOFX] [-m=NOMUSIC] [-p=PRI <priority>]\n[-o=OVERHEAD][[FILE=]<fieldset>]\n", argv[0]);
  160.     cleanexit(EXIT_FAILURE);
  161. }
  162. if (args[0])
  163.     fxable = 3;
  164. if (args[1])
  165.     musicable = 3;
  166. if (args[2])
  167. {    if (args[2] < -128 || args[2] > 5)
  168.        {   Printf("%s: Priority range is -128 to +5\n", argv[0]);
  169.            cleanexit(EXIT_FAILURE);
  170.      }
  171.     OldPri = SetTaskPri((struct Task *) ProcessPtr, args[2]);
  172. }
  173. if (args[3])
  174.     iso = FALSE;
  175. if (args[4])
  176. {    argument = TRUE;
  177.     pathname = args[4];
  178. }
  179.  
  180. enginesetup();
  181.  
  182. if (SysBase->lib_Version < 36L)
  183. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Need exec.library V36+!\0", 24);
  184.     cleanexit(EXIT_FAILURE);
  185. }
  186. if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
  187. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open graphics.library!\0", 24);
  188.     cleanexit(EXIT_FAILURE);
  189. }
  190. if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 37L)))
  191. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open GadTools.library V37+!\0", 24);
  192.     cleanexit(EXIT_FAILURE);
  193. }
  194. if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 0L)))
  195. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open ASL.library!\0", 24);
  196.     cleanexit(EXIT_FAILURE);
  197. }
  198.     
  199. if (!(InputPortPtr = (struct MsgPort *) CreateMsgPort()))
  200. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open input.device!\0", 24);
  201.     cleanexit(EXIT_FAILURE);
  202. }
  203. if (!(InputRqPtr = (struct IOStdReq *) CreateIORequest(InputPortPtr, sizeof(struct IOStdReq))))
  204. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create input I/O request!\0", 24);
  205.     cleanexit(EXIT_FAILURE);
  206. }
  207. if (InputClosed = OpenDevice("input.device", 0, InputRqPtr, 0))
  208. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open input.device!\0", 24);
  209.     cleanexit(EXIT_FAILURE);
  210. }
  211.     
  212. if (!(StartValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  213. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  214.     cleanexit(EXIT_FAILURE);
  215. }
  216. if (!(CurrentValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  217. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  218.     cleanexit(EXIT_FAILURE);
  219. }
  220. if (!(PausedValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  221. {    DisplayAlert(AT_Recovery, ALERTTIMERVALUE, 24);
  222.     cleanexit(EXIT_FAILURE);
  223. }
  224. if (!(TimerPortPtr = (struct MsgPort *) CreateMsgPort()))
  225. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer message port!\0", 24);
  226.     cleanexit(EXIT_FAILURE);
  227. }
  228. if (!(TimerRqPtr = (struct timerequest *) CreateIORequest(TimerPortPtr, sizeof(struct timerequest))))
  229. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create timer I/O request!\0", 24);
  230.     cleanexit(EXIT_FAILURE);
  231. }
  232. if (TimerClosed = OpenDevice(TIMERNAME, UNIT_VBLANK, TimerRqPtr, 0))
  233. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open timer.device!\0", 24);
  234.     cleanexit(EXIT_FAILURE);
  235. }
  236. TimerBase = (struct Library *) TimerRqPtr->tr_node.io_Device;
  237.  
  238. /* PREPARE DISPLAY -----------------------------------------------
  239.  
  240. screen */
  241.  
  242. if (!(ScreenPtr = (struct Screen *) OpenScreenTags(NULL,
  243.     SA_Width,            640,
  244.     SA_Height,            256,
  245.     SA_Depth,            4,
  246.     SA_DisplayID,        HIRES_KEY | PAL_MONITOR_ID,
  247.     SA_Title,            TITLEBAR,
  248.     SA_Colors,            Colours,
  249.     SA_Font,            &Topaz8,
  250.     SA_Pens,            Pens,
  251.     TAG_DONE)))
  252.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen!\0", 24);
  253.         cleanexit(EXIT_FAILURE);
  254.     }
  255.  
  256. // GadTools
  257.  
  258. if (!(CycleGadget.ng_VisualInfo = StringGadget.ng_VisualInfo = CheckboxGadget.ng_VisualInfo = VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)))
  259. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't get GadTools visual info!\0", 24);
  260.     cleanexit(EXIT_FAILURE);
  261. }
  262. if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  263. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create menus!\0", 24);
  264.     cleanexit(EXIT_FAILURE);
  265. }
  266. if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
  267. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't lay out menus!\0", 24);
  268.     cleanexit(EXIT_FAILURE);
  269. }
  270. if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
  271. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools context!\0", 24);
  272.     cleanexit(EXIT_FAILURE);
  273. }
  274. for (player = 0; player <= 3; player++)
  275. {    CycleGadget.ng_TopEdge = 184 + (player * (FONTX + 8));
  276.     CycleGadget.ng_GadgetText = CycleText[player];
  277.     CycleGadgetPtr[player] = PrevGadgetPtr = (struct Gadget *) CreateGadget
  278.     (    CYCLE_KIND,
  279.         PrevGadgetPtr,
  280.         &CycleGadget,
  281.         GTCY_Labels, CycleOptions[player],
  282.         GTCY_Active, worm[player].control,
  283.         GT_Underscore, '_',
  284.         GA_Disabled, TRUE,
  285.         TAG_DONE
  286.     );
  287. }
  288. CheckboxGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
  289. (    CHECKBOX_KIND,
  290.     PrevGadgetPtr,
  291.     &CheckboxGadget,
  292.     GTCB_Checked, iso,
  293.     GT_Underscore, '_',
  294.     GA_Disabled, TRUE,
  295.     TAG_DONE
  296. );
  297.  
  298. // main window
  299.  
  300. if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
  301.     WA_Top,                11,
  302.     WA_Width,            SCREENXPIXEL,
  303.     WA_Height,            SCREENYPIXEL,
  304.     WA_IDCMP,           IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS,
  305.     WA_Gadgets,            GListPtr,
  306.     WA_CustomScreen,    ScreenPtr,
  307.     WA_Borderless,        TRUE,
  308.     WA_Activate,        TRUE,
  309.     WA_SmartRefresh,    TRUE,
  310.     WA_RptQueue,        16,
  311.     TAG_DONE)))
  312.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open main window!\0", 24);
  313.         cleanexit(EXIT_FAILURE);
  314.     }
  315.  
  316. // redirection of AmigaDOS system requesters
  317.     
  318. OldWindowPtr = ProcessPtr->pr_WindowPtr;
  319. ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
  320.  
  321. if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, PATTERN, ASL_Window, MainWindowPtr, TAG_DONE)))
  322. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL request!\0", 24);
  323.     cleanexit(EXIT_FAILURE);
  324. }
  325.  
  326. /* String gadgets: first the window is opened with the cycle and
  327. checkbox gadgets.
  328.     It is necessary not to display the string gadgets yet, so the
  329. gadgets are then created and added to the gadget list. You will note
  330. there is no command given to render them as yet. When the attributes
  331. are modified at highscore time, the applicable gadget is refreshed
  332. then. */
  333.  
  334. for (which = 0; which <= HISCORES; which++)
  335. {    StringGadget.ng_TopEdge = 104 + (which * HISCOREDISTANCE);
  336.     StringGadgetPtr[which] = PrevGadgetPtr = (struct Gadget *) CreateGadget(STRING_KIND, PrevGadgetPtr, &StringGadget, GTST_MaxChars, NAMELENGTH, STRINGA_ReplaceMode, TRUE, GA_Disabled, TRUE, TAG_DONE);
  337. }
  338. if (!PrevGadgetPtr)
  339. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools gadgets!\0", 24);
  340.     cleanexit(EXIT_FAILURE);
  341. }
  342.  
  343. if (!(JoyPortPtr = (struct MsgPort *) CreateMsgPort()))
  344. {    say("Can't create joystick message port!", BLUE);
  345.     anykey(TRUE);
  346. } else if (!(JoyRqPtr = (struct IOStdReq *) CreateIORequest(JoyPortPtr, sizeof(struct IOStdReq))))
  347. {    say("Can't create joystick I/O request!", BLUE);
  348.     anykey(TRUE);
  349. } else if (JoyClosed = OpenDevice("gameport.device", 1, JoyRqPtr, 0))
  350. {    say("Can't open gameport.device!", BLUE);
  351.     anykey(TRUE);
  352. } else
  353. {    Forbid();
  354.     JoyRqPtr->io_Command        = GPD_ASKCTYPE;
  355.     JoyRqPtr->io_Length            = 1;
  356.     JoyRqPtr->io_Flags            = IOF_QUICK;
  357.     JoyRqPtr->io_Data            = (APTR) &Controller;
  358.     DoIO(JoyRqPtr);
  359.     if (Controller == GPCT_NOCONTROLLER)
  360.     {    Controller                = GPCT_ABSJOYSTICK;
  361.         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  362.         JoyRqPtr->io_Length     = 1;
  363.         JoyRqPtr->io_Data        = (APTR) &Controller;
  364.         DoIO(JoyRqPtr);
  365.         success = TRUE;
  366.     }
  367.     Permit();
  368.     /* Note that say(), anykey() calls must be outside the
  369.     Forbid()/Permit() pair. */
  370.     if (success)
  371.     {    JoyRqPtr->io_Command    = GPD_SETTRIGGER;
  372.         JoyRqPtr->io_Data        = (APTR) &Trigger;
  373.         JoyRqPtr->io_Length        = sizeof(struct GamePortTrigger);
  374.         DoIO(JoyRqPtr);
  375.         sendreadrequest();
  376.         joy = TRUE;
  377.     } else
  378.     {    say("Gameport already in use!", BLUE);
  379.         anykey(TRUE);
  380. }    }
  381.  
  382. rememberiso = iso;
  383. iso = FALSE;
  384.  
  385. /* By default, preload music and sound effects at startup.
  386. musicable and fxable values are:
  387.  
  388. 0: tried and failed
  389. 1: tried and succeeded
  390. 2: untried, will load at startup
  391. 3: untried, will load when needed */
  392.  
  393. if (musicable == 2)
  394.     loadthemusic();
  395. if (fxable == 2)
  396.     loadthefx();
  397.  
  398. if (fxable == 1)
  399.     toggle(F);
  400. else if (musicable == 1)
  401.     toggle(M);
  402.  
  403. say("Loading fieldset...", WHITE);
  404. if (argument && !loadfields(pathname))
  405. {    strcpy(saystring, "Can't open ");
  406.     strcat(saystring, pathname);
  407.     strcat(saystring, "!");
  408.     say(saystring, RED);
  409.     anykey(TRUE);
  410.     argument = FALSE;
  411.     pathname = DEFAULTSET;
  412. }
  413. if (!argument && !loadfields(DEFAULTSET))
  414. {    strcpy(saystring, "Can't open ");
  415.     strcat(saystring, DEFAULTSET);
  416.     strcat(saystring, "!");
  417.     say(saystring, RED);
  418.     anykey(TRUE);
  419.     newfields();
  420. }
  421.  
  422. iso = rememberiso;
  423.  
  424. while (1)
  425. {    titlescreen();
  426.  
  427.     // MAIN GAME LOOP -------------------------------------------------
  428.  
  429.     while (a == PLAYGAME)
  430.     {    if (!(++r % VERYSLOW))
  431.         {    GetSysTime(CurrentValPtr);
  432.             SubTime(CurrentValPtr, StartValPtr);
  433.             secondsleft = secondsperlevel - CurrentValPtr->tv_secs;
  434.             timeloop();
  435.         }
  436.         TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  437.         TimerRqPtr->tr_time.tv_secs        = 0;
  438.         TimerRqPtr->tr_time.tv_micro    = delay;
  439.         SendIO(TimerRqPtr);
  440.         gameloop();
  441.         if (CheckIO(TimerRqPtr))
  442.             draw(CLOCKICON, ICONY, CLOCK);
  443.         else
  444.             draw(CLOCKICON, ICONY, BLACKENED);
  445.         WaitIO(TimerRqPtr);
  446.     }
  447.     say("Title Screen", WHITE);
  448. }
  449. }
  450.  
  451. // SUPPORT FUNCTIONS -----------------------------------------------------
  452.  
  453. /* NAME     anykey -- wait for a user press
  454. SYNOPSIS    anykey(ABOOL);
  455. FUNCTION    Waits for a user response. Optional automatic timeout.
  456. INPUTS      timeout - timeout?
  457. RESULTS     FALSE if user presses Escape, TRUE otherwise.
  458. FILE        system.c */
  459.  
  460. ABOOL anykey(ABOOL timeout)
  461. {    ABOOL                    done        = FALSE;
  462.     SBYTE                    count        = 0;
  463.     UWORD                    code, qual;
  464.     ULONG                    class;
  465.     struct IntuiMessage*    MsgPtr;
  466.  
  467.     clearkybd();
  468.     Forbid();
  469.     MainWindowPtr->Flags |= WFLG_RMBTRAP;
  470.     Permit();
  471.     
  472.     while (!done)
  473.     {    if (joy && GetMsg(JoyPortPtr))
  474.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  475.                 done = TRUE;
  476.             sendreadrequest();
  477.         }
  478.         if (joy)
  479.         {    Wait((1L << MainWindowPtr->UserPort->mp_SigBit) | (1L << JoyPortPtr->mp_SigBit));
  480.             while (GetMsg(JoyPortPtr))
  481.             {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  482.                     done = TRUE;
  483.                 sendreadrequest();
  484.         }    }
  485.         else Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  486.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  487.         {    class = MsgPtr->Class;
  488.             code  = MsgPtr->Code;
  489.             qual  = MsgPtr->Qualifier;
  490.             GT_ReplyIMsg(MsgPtr);
  491.             switch(class)
  492.             {
  493.             case IDCMP_RAWKEY:
  494.                 if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
  495.                 {    done = TRUE;
  496.                     if (code == M)
  497.                         toggle(M);
  498.                     else if (code == F)
  499.                         toggle(F);
  500.                     else if (code == ESCAPE)
  501.                     {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  502.                         {    if (verify())
  503.                                 cleanexit(EXIT_SUCCESS);
  504.                         } else
  505.                         {    Forbid();
  506.                             MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  507.                             Permit();
  508.                             return FALSE;
  509.                 }   }    }
  510.                 break;
  511.             case IDCMP_CLOSEWINDOW:
  512.                 cleanexit(EXIT_SUCCESS);
  513.                 break;
  514.             case IDCMP_ACTIVEWINDOW:
  515.                 ignore = TRUE;
  516.                 break;
  517.             case IDCMP_MOUSEBUTTONS:
  518.                 if ((code == SELECTDOWN || code == MENUDOWN) && !(qual & IEQUALIFIER_REPEAT))
  519.                     if (ignore)
  520.                         ignore = FALSE;
  521.                     else done = TRUE;
  522.                 break;
  523.             case IDCMP_INTUITICKS:
  524.                 if (timeout && ++count > PATIENCE)
  525.                     done = TRUE;
  526.                 break;
  527.             default:
  528.                 break;
  529.     }    }    }
  530.  
  531.     Forbid();
  532.     MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  533.     Permit();
  534.     return TRUE;
  535. }
  536.  
  537. void celebrate(void)
  538. {    ABOOL                    done = FALSE;
  539.     ULONG                    class;
  540.     UWORD                    code, qual;
  541.     struct IntuiMessage*    MsgPtr;
  542.  
  543.     waitasec();
  544.     clearkybd();
  545.     while (done == FALSE)
  546.     {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  547.         {    class = MsgPtr->Class;
  548.             code  = MsgPtr->Code;
  549.             qual  = MsgPtr->Qualifier;
  550.             GT_ReplyIMsg(MsgPtr);
  551.             switch (class)
  552.             {
  553.             case IDCMP_RAWKEY:
  554.                 if (code == ESCAPE)
  555.                 {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  556.                     {    if (verify())
  557.                             cleanexit(EXIT_SUCCESS);
  558.                     } else
  559.                         done = TRUE;
  560.                 }
  561.                 else if (code == RETURN || code == ENTER || code == SPACEBAR)
  562.                     done = TRUE;
  563.                 else if (code == M)
  564.                     toggle(M);
  565.                 else if (code == F)
  566.                     toggle(F);
  567.                 break;
  568.             case IDCMP_MOUSEBUTTONS:
  569.                 if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
  570.                     if (ignore)
  571.                         ignore = FALSE;
  572.                     else done = TRUE;
  573.                 break;
  574.             case IDCMP_ACTIVEWINDOW:
  575.                 ignore = TRUE;
  576.                 break;
  577.             case IDCMP_CLOSEWINDOW:
  578.                 cleanexit(EXIT_SUCCESS);
  579.                 break;
  580.             default:
  581.                 break;
  582.         }    }
  583.         if (joy && GetMsg(JoyPortPtr))
  584.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  585.                 done = TRUE;
  586.             sendreadrequest();
  587.         }
  588.         SetRGB4(&ScreenPtr->ViewPort, 17, rand() % 16, rand() % 16, rand() % 16);
  589.         draw(rand() % (FIELDX + 1), rand() % (FIELDY + 1), rand() % LASTOBJECT);
  590.     }
  591.     SetRGB4(&ScreenPtr->ViewPort, 17, 14, 4, 4);
  592.     a = GAMEOVER;
  593. }
  594.  
  595. void cleanexit(SLONG rc)
  596. {   SBYTE i;
  597.     
  598. if (TimerRqPtr && (!CheckIO(TimerRqPtr)))
  599.                     {    AbortIO(TimerRqPtr);
  600.                         WaitIO(TimerRqPtr);                                }
  601.                         freefx();
  602.                         for (i = 0; i <= SAMPLES; i++)
  603.                             if (sbase[i])
  604.                                 FreeMem(sbase[i], ssize[i]);
  605. if (mode == MUSIC)        StopPlayer();
  606. if (SongPtr)            UnLoadModule(SongPtr);
  607. if (MEDPlayerBase)    {    FreePlayer();
  608.                         CloseLibrary(MEDPlayerBase);                    }
  609.  
  610. if (joy)            {    AbortIO(JoyRqPtr);
  611.                         WaitIO(JoyRqPtr);                                }
  612. if (Controller != GPCT_NOCONTROLLER)
  613.                     {    Forbid();
  614.                         Controller                = GPCT_NOCONTROLLER;
  615.                         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  616.                         JoyRqPtr->io_Length        = 1;
  617.                         JoyRqPtr->io_Data        = (APTR) &Controller;
  618.                         DoIO(JoyRqPtr);
  619.                         Permit();                                        }
  620. if (!JoyClosed)            CloseDevice(JoyRqPtr);
  621. if (JoyRqPtr)            DeleteIORequest(JoyRqPtr);
  622. if (JoyPortPtr)            DeleteMsgPort(JoyPortPtr);
  623.  
  624. if (ASLRqPtr)            FreeAslRequest(ASLRqPtr);
  625. if (OldWindowPtr)        ProcessPtr->pr_WindowPtr = OldWindowPtr;
  626. if (MainWindowPtr)    {    clearkybd();
  627.                         ClearMenuStrip(MainWindowPtr);
  628.                         CloseWindow(MainWindowPtr);                        }
  629. if (GListPtr)            FreeGadgets(GListPtr);
  630. if (MenuPtr)            FreeMenus(MenuPtr);
  631. if (VisualInfoPtr)        FreeVisualInfo(VisualInfoPtr);
  632.  
  633. if (ScreenPtr)            CloseScreen(ScreenPtr);
  634. if (!TimerClosed)        CloseDevice(TimerRqPtr);
  635. if (TimerRqPtr)            DeleteIORequest(TimerRqPtr);
  636. if (TimerPortPtr)        DeleteMsgPort(TimerPortPtr);
  637. if (PausedValPtr)        FreeMem(PausedValPtr, sizeof(struct timeval));
  638. if (CurrentValPtr)        FreeMem(CurrentValPtr, sizeof(struct timeval));
  639. if (StartValPtr)        FreeMem(StartValPtr, sizeof(struct timeval));
  640. if (!InputClosed)        CloseDevice(InputRqPtr);
  641. if (InputRqPtr)            DeleteIORequest(InputRqPtr);
  642. if (InputPortPtr)        DeleteMsgPort(InputPortPtr);
  643. if (ASLBase)            CloseLibrary(ASLBase);
  644. if (GadToolsBase)        CloseLibrary(GadToolsBase);
  645. if (GfxBase)            CloseLibrary(GfxBase);
  646. if (IntuitionBase)    {    OpenWorkBench();
  647.                         CloseLibrary(IntuitionBase);                    }
  648.                         SetTaskPri((struct Task *) ProcessPtr, OldPri);
  649. if (ArgsPtr)            FreeArgs(ArgsPtr);
  650.                         exit(rc);                // End of program.
  651. }
  652.  
  653. void clearjoystick(void)
  654. {    if (joy)
  655.         while (GetMsg(JoyPortPtr))
  656.             sendreadrequest();
  657. }
  658.  
  659. void clearkybd(void)
  660. {    struct IntuiMessage* MsgPtr;
  661.  
  662.     while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  663.         GT_ReplyIMsg(MsgPtr);
  664. }
  665.  
  666. void clearstats(void)
  667. {    SetAPen(MainWindowPtr->RPort, BLACK);
  668.     RectFill(MainWindowPtr->RPort, 0, STARTYPIXEL, STARTXPIXEL - 1, ENDYPIXEL);
  669.     RectFill(MainWindowPtr->RPort, ENDXPIXEL + 1, STARTYPIXEL, SCREENXPIXEL, SCREENYPIXEL);
  670.     if (mode == MUSIC)
  671.         draw(MUSICICON, ICONY, MUSIC);
  672.     else if (mode == FX)
  673.         draw(MUSICICON, ICONY, FX);
  674.     if (sticky)
  675.         draw(STICKYICON, ICONY, STICKY);
  676. }
  677.  
  678. void draw(SBYTE x, SBYTE y, SBYTE image)
  679. {    SWORD pixx;
  680.     
  681.     /* Isometric methodology:
  682.     
  683.     read the colour of the pixel, then set the colour in the image
  684.     to the same value.
  685.  
  686.     So if, for the top left pixel, we read colour 10 (= $A or %1010),
  687.     we have to clear the relevant bits in plane 0 and 2, and set them
  688.     in planes 1 and 3.
  689.  
  690.     plane 0 (least significant bit)
  691.         1234567890123456 pixels for top row (y = 0)
  692.         1234567890123456 pixels for next row (y = 1)
  693.         : : :
  694.     plane 1
  695.         : : :
  696.  
  697.      01234567890
  698.     0..#########
  699.     1..#########
  700.     2.#########.
  701.     3.#########.
  702.     4#########..
  703.     5#########..
  704.  
  705.     Image is effectively 9*6, but requires an 11*6 bitmap.
  706.  
  707.      31
  708.      268421
  709.      731000521
  710.      689942152631
  711.      8426842684268421
  712.      **.......**..... */
  713.  
  714.     if (iso)
  715.     {    IsoImage.ImageData = IsoImageData[image];
  716.         pixx = (x * ISOSQUAREX) + 20 + ((FIELDY - y) * 3);
  717.         pixy = (y * ISOSQUAREY) + STARTYPIXEL;
  718.         preserve(pixx,      0, image, 32768);
  719.         preserve(pixx,      1, image, 32768);
  720.         preserve(pixx,      2, image, 32768);
  721.         preserve(pixx,      3, image, 32768);
  722.         preserve(pixx +  1, 0, image, 16384);
  723.         preserve(pixx +  1, 1, image, 16384);
  724.         preserve(pixx +  9, 4, image,    64);
  725.         preserve(pixx +  9, 5, image,    64);
  726.         preserve(pixx + 10, 2, image,    32);
  727.         preserve(pixx + 10, 3, image,    32);
  728.         preserve(pixx + 10, 4, image,    32);
  729.         preserve(pixx + 10, 5, image,    32);
  730.         DrawImage
  731.         (    MainWindowPtr->RPort,
  732.             &IsoImage,
  733.             pixx,
  734.             pixy
  735.         );
  736.     } else
  737.     {    Image.ImageData = ImageData[image];
  738.         DrawImage
  739.         (    MainWindowPtr->RPort,
  740.             &Image,
  741.             (x * SQUAREX) + STARTXPIXEL,
  742.             (y * SQUAREY) + STARTYPIXEL
  743.         );
  744. }    }
  745.  
  746. void preserve(SWORD x, SBYTE row, SBYTE image, UWORD amount)
  747. {    LONG colour;
  748.     
  749.     /* x = image top-left corner coordinate on destination screen.
  750.     row = y-row of the image.
  751.     image = image number
  752.     amount = value of the bit to be set/cleared. */
  753.  
  754.     colour = ReadPixel
  755.     (    MainWindowPtr->RPort,
  756.         x,
  757.         pixy + row
  758.     );
  759.     if (colour & 8)
  760.         IsoImageData[image][row + 18] |= amount;
  761.     else IsoImageData[image][row + 18] &= ~amount;
  762.     if (colour & 4)
  763.         IsoImageData[image][row + 12] |= amount;
  764.     else IsoImageData[image][row + 12] &= ~amount;
  765.     if (colour & 2)
  766.         IsoImageData[image][row + 6] |= amount;
  767.     else IsoImageData[image][row + 6] &= ~amount;
  768.     if (colour & 1)
  769.         IsoImageData[image][row] |= amount;
  770.     else IsoImageData[image][row] &= ~amount;
  771. }
  772.  
  773. ULONG effect(SBYTE index)
  774. {           SBYTE    i;
  775.             SBYTE    ok                = -1;
  776.             ULONG   oldestreceipt    = (ULONG) -1L;
  777.     PERSIST    ULONG   receipt            = 1L;
  778.  
  779.     /* oldestreceipt = temporary variable for ascertaining oldest
  780.     sound still playing.
  781.     receipt = next unused receipt number (monotonically incrementing). */
  782.  
  783.     if (mode == FX)
  784.     {    for (i = 0; i <= 3; i++)
  785.         {    // decide on a channel
  786.  
  787.             if (ok == -1)
  788.             {    if (!eversent[i])
  789.                     ok = i;
  790.                 else if (CheckIO(AudioRqPtr[i]))
  791.                 {    WaitIO(AudioRqPtr[i]);
  792.                     ok = i;
  793.         }    }    }
  794.         if (ok == -1)
  795.         {   for (i = 0; i <= 3; i++)
  796.                 if (receipter[i] < oldestreceipt)
  797.                 {   ok = i;
  798.                     oldestreceipt = receipter[i];
  799.                 }
  800.             AbortIO(AudioRqPtr[ok]);
  801.             WaitIO(AudioRqPtr[ok]);
  802.         }
  803.         eversent[ok] = TRUE;
  804.         AudioRqPtr[ok]->ioa_Cycles                = 1;
  805.         AudioRqPtr[ok]->ioa_Request.io_Command  = CMD_WRITE;
  806.         AudioRqPtr[ok]->ioa_Request.io_Flags    = ADIOF_PERVOL;
  807.         AudioRqPtr[ok]->ioa_Request.io_Unit     = (1 << ok);
  808.         AudioRqPtr[ok]->ioa_Volume              = samp[index].volume;
  809.         AudioRqPtr[ok]->ioa_Period              = (UWORD) speed[index];
  810.         AudioRqPtr[ok]->ioa_Request.io_Message.mn_ReplyPort
  811.                                                 = AudioPortPtr[ok];
  812.         AudioRqPtr[ok]->ioa_Data                = (UBYTE *) sbase[index];
  813.         AudioRqPtr[ok]->ioa_Length              = length[index][yes[index]];
  814.         BeginIO(AudioRqPtr[ok]);
  815.         receipter[ok] = receipt;
  816.         return(receipt++);
  817. }   }
  818.  
  819. void fieldedit(void)
  820. {        UBYTE                    oldbrush = ANYTHING, stamp;
  821.         SBYTE                    deltax = 0, deltay = 0, lastx, lasty, pointerx, pointery, which, x, y;
  822.         UWORD                    code, qual;
  823.         ULONG                    class;
  824.         struct IntuiMessage*    MsgPtr;
  825.         ABOOL                    leftdown = FALSE, rightdown = FALSE, timer = FALSE;
  826.         ABOOL                    rememberiso;
  827.         struct MenuItem*        ItemPtr;
  828. PERSIST    SBYTE                    clipboard[FIELDX + 1][FIELDY + 1];
  829. PERSIST    ABOOL                    clipboarded = FALSE;
  830.  
  831. rememberiso = iso;
  832. iso = FALSE;
  833. say("Field Editor", WHITE);
  834. setpointer(brush);
  835. if (level > levels)
  836.     level = levels;
  837. OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  838. OnMenu(MainWindowPtr, FULLMENUNUM(MN_LEVEL, NOITEM, NOSUB));
  839. if (!clipboarded)
  840.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  841.  
  842. // draw pseudo-gadgets
  843.  
  844. clearstats();
  845. for (which = 0; which <= 8; which++)
  846.     DrawBevelBox(MainWindowPtr->RPort, STARTXPIXEL - 5 - (SQUAREX * 3), 40 + STARTYPIXEL + (which * SQUAREY * 3), SQUAREX + 9, SQUAREY + 4, GT_VisualInfo, VisualInfoPtr);
  847. SetAPen(MainWindowPtr->RPort, WHITE);
  848. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  GOLDGADGET * SQUAREY));
  849. Text(MainWindowPtr->RPort, "F1:", 3);
  850. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (SILVERGADGET * SQUAREY));
  851. Text(MainWindowPtr->RPort, "F2:", 3);
  852. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( EMPTYGADGET * SQUAREY));
  853. Text(MainWindowPtr->RPort, "F3:", 3);
  854. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  WOODGADGET * SQUAREY));
  855. Text(MainWindowPtr->RPort, "F4:", 3);
  856. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STONEGADGET * SQUAREY));
  857. Text(MainWindowPtr->RPort, "F5:", 3);
  858. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( METALGADGET * SQUAREY));
  859. Text(MainWindowPtr->RPort, "F6:", 3);
  860. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   ONEGADGET * SQUAREY));
  861. Text(MainWindowPtr->RPort, "F7:", 3);
  862. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   TWOGADGET * SQUAREY));
  863. Text(MainWindowPtr->RPort, "F8:", 3);
  864. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STARTGADGET * SQUAREY));
  865. Text(MainWindowPtr->RPort, "F9:", 3);
  866. draw(GADGETX,   GOLDGADGET,   GOLD);
  867. draw(GADGETX, SILVERGADGET, SILVER);
  868. draw(GADGETX,  EMPTYGADGET,  EMPTY);
  869. draw(GADGETX,   WOODGADGET,   WOOD);
  870. draw(GADGETX,  STONEGADGET,  STONE);
  871. draw(GADGETX,  METALGADGET,  METAL);
  872. draw(GADGETX,    ONEGADGET,       ONE);
  873. draw(GADGETX,    TWOGADGET,    TWO);
  874. draw(GADGETX,  STARTGADGET,  START);
  875. underline(brush);
  876.  
  877. renderboard();
  878. saylevel(WHITE);
  879. clearkybd();
  880. x = lastx = startx[level];
  881. y = lasty = starty[level];
  882.     
  883. while (a == FIELDEDIT)
  884. {    stamp = NOSQUARE;
  885.  
  886.     if (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  887.     {    class = MsgPtr->Class;
  888.         code  = MsgPtr->Code;
  889.         qual  = MsgPtr->Qualifier;
  890.         if (class == IDCMP_MENUVERIFY && MsgPtr->MouseX >= STARTXPIXEL && MsgPtr->MouseX <= ENDXPIXEL && MsgPtr->MouseY >= STARTYPIXEL && MsgPtr->MouseY <= ENDYPIXEL)
  891.         {    MsgPtr->Code = MENUCANCEL;
  892.             oldbrush = brush;
  893.             brush = EMPTY;
  894.             rightdown = TRUE;
  895.         }
  896.         ReplyMsg(MsgPtr);
  897.         switch (class)
  898.         {
  899.         case IDCMP_MENUPICK:
  900.             while (code != MENUNULL)
  901.             {    ItemPtr = ItemAddress(MenuPtr, code);
  902.                 switch (MENUNUM(code))
  903.                 {
  904.                 case MN_PROJECT:
  905.                     switch (ITEMNUM(code))
  906.                     {
  907.                     case IN_NEW:
  908.                         effect(FXFILENEW);
  909.                         newfields();
  910.                         say("New done.", WHITE);
  911.                         break;
  912.                     case IN_OPEN:
  913.                         effect(FXFILEOPEN);
  914.                         fileopen();
  915.                         break;
  916.                     case IN_SAVE:
  917.                         effect(FXFILESAVE);
  918.                         if (modified)
  919.                         {    clearhiscores();
  920.                             modified = FALSE;
  921.                         }
  922.                         filesaveas(FALSE);
  923.                         break;
  924.                     case IN_SAVEAS:
  925.                         effect(FXFILESAVEAS);
  926.                         if (modified)
  927.                         {    clearhiscores();
  928.                             modified = FALSE;
  929.                         }
  930.                         filesaveas(TRUE);
  931.                         break;
  932.                     case IN_ABOUT:
  933.                         fileabout();
  934.                         break;
  935.                     case IN_QUIT:
  936.                         if (verify())
  937.                             cleanexit(EXIT_SUCCESS);
  938.                         break;
  939.                     default:
  940.                         break;
  941.                     }
  942.                     break;
  943.                 case MN_EDIT:
  944.                     switch (ITEMNUM(code))
  945.                     {
  946.                     case IN_CUT:
  947.                         for (x = 0; x <= FIELDX; x++)
  948.                             for (y = 0; y <= FIELDY; y++)
  949.                                 clipboard[x][y] = board[level][x][y];
  950.                         leveldelete();
  951.                         clipboarded = TRUE;
  952.                         OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  953.                         break;
  954.                     case IN_COPY:
  955.                         for (x = 0; x <= FIELDX; x++)
  956.                             for (y = 0; y <= FIELDY; y++)
  957.                                 clipboard[x][y] = board[level][x][y];
  958.                         clipboarded = TRUE;
  959.                         OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  960.                         break;
  961.                     case IN_PASTE:
  962.                         for (x = 0; x <= FIELDX; x++)
  963.                             for (y = 0; y <= FIELDY; y++)
  964.                                 board[level][x][y] = clipboard[x][y];
  965.                         renderboard();
  966.                         break;
  967.                     default:
  968.                         break;
  969.                     }
  970.                     break;
  971.                 case MN_LEVEL:
  972.                     switch (ITEMNUM(code))
  973.                     {
  974.                     case IN_INSERT:
  975.                         levelinsert();
  976.                         break;
  977.                     case IN_DELETE:
  978.                         leveldelete();
  979.                         break;
  980.                     case IN_ERASE:
  981.                         levelerase();
  982.                         break;
  983.                     case IN_APPEND:
  984.                         levelappend();
  985.                         break;
  986.                     default:
  987.                         break;
  988.                     }
  989.                     break;
  990.                 default:
  991.                     break;
  992.                 }
  993.                 code = ItemPtr->NextSelect;
  994.             }
  995.             break;
  996.         case IDCMP_RAWKEY:
  997.             lastx = x;
  998.             lasty = y;
  999.             switch(code)
  1000.             {
  1001.             case DELETE:
  1002.                 if (!(qual & IEQUALIFIER_REPEAT))
  1003.                 {    effect(FXCLICK);
  1004.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1005.                         level = 1;
  1006.                     else if (--level < 0)
  1007.                         level = levels;
  1008.                     saylevel(WHITE);
  1009.                     renderboard();
  1010.                 }
  1011.                 break;
  1012.             case HELP:
  1013.                 if (!(qual & IEQUALIFIER_REPEAT))
  1014.                 {    effect(FXCLICK);
  1015.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1016.                         level = levels;
  1017.                     else if (++level > levels)
  1018.                         level = 0;
  1019.                     saylevel(WHITE);
  1020.                     renderboard();
  1021.                 }
  1022.                 break;
  1023.             case M:
  1024.                 if (!(qual & IEQUALIFIER_REPEAT))
  1025.                     toggle(M);
  1026.                 break;
  1027.             case F:
  1028.                 if (!(qual & IEQUALIFIER_REPEAT))
  1029.                     toggle(F);
  1030.                 break;
  1031.             case ESCAPE:
  1032.                 if (!(qual & IEQUALIFIER_REPEAT))
  1033.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1034.                     {   if (verify())
  1035.                             cleanexit(EXIT_SUCCESS);
  1036.                     } else a = GAMEOVER;
  1037.                 break;
  1038.             case SPACEBAR:
  1039.             case RETURN:
  1040.             case ENTER:
  1041.                 if (!(qual & IEQUALIFIER_REPEAT))
  1042.                     a = GAMEOVER;
  1043.                 break;
  1044.             case N:
  1045.                 if (!(qual & IEQUALIFIER_REPEAT))
  1046.                 {    effect(FXFILENEW);
  1047.                     newfields();
  1048.                     say("New done.", WHITE);
  1049.                 }
  1050.                 break;
  1051.             case O:
  1052.                 if (!(qual & IEQUALIFIER_REPEAT))
  1053.                 {    effect(FXFILEOPEN);
  1054.                     fileopen();
  1055.                 }
  1056.                 break;
  1057.             case S:
  1058.                 if (!(qual & IEQUALIFIER_REPEAT))
  1059.                 {    effect(FXFILESAVE);
  1060.                     if (modified)
  1061.                     {    clearhiscores();
  1062.                         modified = FALSE;
  1063.                     }
  1064.                     filesaveas(FALSE);
  1065.                 }
  1066.                 break;
  1067.             case A:
  1068.                 if (!(qual & IEQUALIFIER_REPEAT))
  1069.                 {   effect(FXFILESAVEAS);
  1070.                     if (modified)
  1071.                     {    clearhiscores();
  1072.                         modified = FALSE;
  1073.                     }
  1074.                     filesaveas(TRUE);
  1075.                 }
  1076.                 break;
  1077.             case Q:
  1078.                 if (!(qual & IEQUALIFIER_REPEAT))
  1079.                 {   if (verify())
  1080.                         cleanexit(EXIT_SUCCESS);
  1081.                 }
  1082.                 break;
  1083.             case NUMERICOPEN:
  1084.                 effect(FXCLICK);
  1085.                 setpointer(NORMAL);
  1086.                 underline(-1);
  1087.                 if (brush-- == 0 || brush > LASTOBJECT)
  1088.                     brush = LASTOBJECT;
  1089.                 stamp = brush;
  1090.                 break;
  1091.             case NUMERICCLOSE:
  1092.                 effect(FXCLICK);
  1093.                 setpointer(NORMAL);
  1094.                 underline(-1);
  1095.                 if (++brush > LASTOBJECT)
  1096.                     brush = 0;
  1097.                 stamp = brush;
  1098.                 break;
  1099.             case I:
  1100.                 effect(FXCLICK);
  1101.                 if (!(qual & IEQUALIFIER_REPEAT))
  1102.                     levelinsert();
  1103.                 break;
  1104.             case D:
  1105.                 effect(FXCLICK);
  1106.                 if (!(qual & IEQUALIFIER_REPEAT) && ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT)))
  1107.                     leveldelete();
  1108.                 break;
  1109.             case E:
  1110.                 effect(FXCLICK);
  1111.                 if (!(qual & IEQUALIFIER_REPEAT) && ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT)))
  1112.                     levelerase();
  1113.                 break;
  1114.             case K:
  1115.                 effect(FXCLICK);
  1116.                 if (!(qual & IEQUALIFIER_REPEAT))
  1117.                     levelappend();
  1118.                 break;
  1119.             case ALPHAONE:
  1120.                 effect(FXCLICK);
  1121.                 stamp = GOLD;
  1122.                 break;
  1123.             case ALPHATWO:
  1124.                 effect(FXCLICK);
  1125.                 stamp = SILVER;
  1126.                 break;
  1127.             case ALPHATHREE:
  1128.                 effect(FXCLICK);
  1129.                 stamp = EMPTY;
  1130.                 break;
  1131.             case ALPHAFOUR:
  1132.                 effect(FXCLICK);
  1133.                 stamp = WOOD;
  1134.                 break;
  1135.             case ALPHAFIVE:
  1136.                 effect(FXCLICK);
  1137.                 stamp = STONE;
  1138.                 break;
  1139.             case ALPHASIX:
  1140.                 effect(FXCLICK);
  1141.                 stamp = METAL;
  1142.                 break;
  1143.             case ALPHASEVEN:
  1144.                 effect(FXCLICK);
  1145.                 stamp = ONE;
  1146.                 break;
  1147.             case ALPHAEIGHT:
  1148.                 effect(FXCLICK);
  1149.                 stamp = TWO;
  1150.                 break;
  1151.             case ALPHANINE:
  1152.                 effect(FXCLICK);
  1153.                 stamp = START;
  1154.                 break;
  1155.             case F1:
  1156.                 if (!(qual & IEQUALIFIER_REPEAT))
  1157.                 {    effect(FXCLICK);
  1158.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1159.                         fillfield(GOLD);
  1160.                     else setbrush(GOLD);
  1161.                 }
  1162.                 break;
  1163.             case F2:
  1164.                 if (!(qual & IEQUALIFIER_REPEAT))
  1165.                 {    effect(FXCLICK);
  1166.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1167.                         fillfield(SILVER);
  1168.                     else setbrush(SILVER);
  1169.                 }
  1170.                 break;
  1171.             case F3:
  1172.                 if (!(qual & IEQUALIFIER_REPEAT))
  1173.                 {    effect(FXCLICK);
  1174.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1175.                         fillfield(EMPTY);
  1176.                     else setbrush(EMPTY);
  1177.                 }
  1178.                 break;
  1179.             case F4:
  1180.                 if (!(qual & IEQUALIFIER_REPEAT))
  1181.                 {    effect(FXCLICK);
  1182.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1183.                         fillfield(WOOD);
  1184.                     else setbrush(WOOD);
  1185.                 }
  1186.                 break;
  1187.             case F5:
  1188.                 if (!(qual & IEQUALIFIER_REPEAT))
  1189.                 {    effect(FXCLICK);
  1190.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1191.                         fillfield(STONE);
  1192.                     else setbrush(STONE);
  1193.                 }
  1194.                 break;
  1195.             case F6:
  1196.                 if (!(qual & IEQUALIFIER_REPEAT))
  1197.                 {    effect(FXCLICK);
  1198.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1199.                         fillfield(METAL);
  1200.                     else setbrush(METAL);
  1201.                 }
  1202.                 break;
  1203.             case F7:
  1204.                 if (!(qual & IEQUALIFIER_REPEAT))
  1205.                 {    effect(FXCLICK);
  1206.                     setbrush(ONE);
  1207.                 }
  1208.                 break;
  1209.             case F8:
  1210.                 if (!(qual & IEQUALIFIER_REPEAT))
  1211.                 {    effect(FXCLICK);
  1212.                     setbrush(TWO);
  1213.                 }
  1214.                 break;
  1215.             case F9:
  1216.                 if (!(qual & IEQUALIFIER_REPEAT))
  1217.                 {    effect(FXCLICK);
  1218.                     setbrush(START);
  1219.                 }
  1220.                 break;
  1221.             case NUMERICZERO:
  1222.                 effect(FXCLICK);
  1223.                 if (!(qual & IEQUALIFIER_REPEAT))
  1224.                 {    if (!sticky)
  1225.                     {    sticky = TRUE;
  1226.                         draw(STICKYICON, ICONY, STICKY);
  1227.                         stamp = brush;
  1228.                     } else
  1229.                     {    sticky = FALSE;
  1230.                         draw(STICKYICON, ICONY, BLACKENED);
  1231.                 }    }
  1232.                 break;
  1233.             case NUMERICDOT:
  1234.                 effect(FXCLICK);
  1235.                 if (!(qual & IEQUALIFIER_REPEAT))
  1236.                     stamp = brush;
  1237.                 break;
  1238.             case NUMERICFOUR:
  1239.             case LEFT:
  1240.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1241.                     x = 0;
  1242.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1243.                     x = xwrap(x - ALTJUMP);
  1244.                 else
  1245.                     x = xwrap(x - 1);
  1246.                 if (sticky)
  1247.                     stamp = brush;
  1248.                 break;
  1249.             case NUMERICSIX:
  1250.             case RIGHT:
  1251.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1252.                     x = FIELDX;
  1253.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1254.                     x = xwrap(x + ALTJUMP);
  1255.                 else
  1256.                     x = xwrap(x + 1);
  1257.                 if (sticky)
  1258.                     stamp = brush;
  1259.                 break;
  1260.             case NUMERICEIGHT:
  1261.             case UP:
  1262.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1263.                     y = 0;
  1264.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1265.                     y = ywrap(y - ALTJUMP);
  1266.                 else
  1267.                     y = ywrap(y - 1);
  1268.                 if (sticky)
  1269.                     stamp = brush;
  1270.                 break;
  1271.             case NUMERICFIVE:
  1272.             case NUMERICTWO:
  1273.             case DOWN:
  1274.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1275.                     y = FIELDY;
  1276.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1277.                     y = ywrap(y + ALTJUMP);
  1278.                 else
  1279.                     y = ywrap(y + 1);
  1280.                 if (sticky)
  1281.                     stamp = brush;
  1282.                 break;
  1283.             case NUMERICSEVEN:
  1284.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1285.                 {    x = 0;
  1286.                     y = 0;
  1287.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1288.                 {    x = xwrap(x - ALTJUMP);
  1289.                     y = ywrap(y - ALTJUMP);
  1290.                 } else
  1291.                 {    x = xwrap(x - 1);
  1292.                     y = ywrap(y - 1);
  1293.                 }
  1294.                 if (sticky)
  1295.                     stamp = brush;
  1296.                 break;
  1297.             case NUMERICNINE:
  1298.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1299.                 {    x = FIELDX;
  1300.                     y = 0;
  1301.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1302.                 {    x = xwrap(x + ALTJUMP);
  1303.                     y = ywrap(y - ALTJUMP);
  1304.                 } else
  1305.                 {    x = xwrap(x + 1);
  1306.                     y = ywrap(y - 1);
  1307.                 }
  1308.                 if (sticky)
  1309.                     stamp = brush;
  1310.                 break;
  1311.             case NUMERICONE:
  1312.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1313.                 {    x = 0;
  1314.                     y = FIELDY;
  1315.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1316.                 {    x = xwrap(x - ALTJUMP);
  1317.                     y = ywrap(y + ALTJUMP);
  1318.                 } else
  1319.                 {    x = xwrap(x - 1);
  1320.                     y = ywrap(y + 1);
  1321.                 }
  1322.                 if (sticky)
  1323.                     stamp = brush;
  1324.                 break;
  1325.             case NUMERICTHREE:
  1326.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1327.                 {    x = FIELDX;
  1328.                     y = FIELDY;
  1329.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1330.                 {    x = xwrap(x + ALTJUMP);
  1331.                     y = ywrap(y + ALTJUMP);
  1332.                 } else
  1333.                 {    x = xwrap(x + 1);
  1334.                     y = ywrap(y + 1);
  1335.                 }
  1336.                 if (sticky)
  1337.                     stamp = brush;
  1338.                 break;
  1339.             default:
  1340.                 break;
  1341.             }
  1342.             if (x != lastx || y != lasty)
  1343.             {    updatesquare(lastx, lasty);
  1344.                 if (stamp == NOSQUARE)
  1345.                     dot(x, y);
  1346.             }
  1347.             break;
  1348.         case IDCMP_MOUSEBUTTONS:
  1349.             updatesquare(x, y);
  1350.             switch (code)
  1351.             {
  1352.             case SELECTUP:
  1353.                 leftdown = FALSE;
  1354.                 break;
  1355.             case SELECTDOWN:
  1356.                 if (!ignore)
  1357.                 {    effect(FXCLICK);
  1358.                     leftdown = TRUE;
  1359.                 }
  1360.                 break;
  1361.             case MENUUP:
  1362.                 rightdown = FALSE;
  1363.                 brush = oldbrush;
  1364.                 oldbrush = ANYTHING;
  1365.                 break;
  1366.             default:
  1367.                 // MENUDOWN
  1368.                 break;
  1369.             }
  1370.             break;
  1371.         case IDCMP_ACTIVEWINDOW:
  1372.             ignore = TRUE;
  1373.             break;
  1374.         case IDCMP_CLOSEWINDOW:
  1375.             cleanexit(EXIT_SUCCESS);
  1376.             break;
  1377.         case IDCMP_REFRESHWINDOW:
  1378.             GT_BeginRefresh(MainWindowPtr);
  1379.             GT_EndRefresh(MainWindowPtr, TRUE);
  1380.             break;
  1381.         default:
  1382.             // IDCMP_MENUVERIFY, IDCMP_INTUITICKS
  1383.             break;
  1384.     }    }
  1385.     else if (joy)
  1386.     {    if (GetMsg(JoyPortPtr))
  1387.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  1388.                 stamp = brush;
  1389.             deltax = (SBYTE) GameEvent.ie_position.ie_xy.ie_x;
  1390.             deltay = (SBYTE) GameEvent.ie_position.ie_xy.ie_y;
  1391.             if (GameEvent.ie_Qualifier == IEQUALIFIER_LEFTBUTTON)
  1392.                 stamp = brush;
  1393.             sendreadrequest();
  1394.         }
  1395.         if (deltax || deltay)
  1396.         {    if (!timer)
  1397.             {    TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  1398.                 TimerRqPtr->tr_time.tv_secs        = 0;
  1399.                 TimerRqPtr->tr_time.tv_micro    = JOYDELAY;
  1400.                 SendIO(TimerRqPtr);
  1401.                 timer = TRUE;
  1402.             } else if (CheckIO(TimerRqPtr))
  1403.             {    lastx = x;
  1404.                 lasty = y;
  1405.                 x = xwrap(x + deltax);
  1406.                 y = ywrap(y + deltay);    
  1407.                 updatesquare(lastx, lasty);
  1408.                 if (stamp == NOSQUARE)
  1409.                        dot(x, y);
  1410.                 timer = FALSE;
  1411.     }    }    }
  1412.     if (leftdown || rightdown)
  1413.     {    pointerx = xpixeltosquare(MainWindowPtr->MouseX);
  1414.         pointery = ypixeltosquare(MainWindowPtr->MouseY);
  1415.         if (valid(pointerx, pointery))
  1416.         {    x = pointerx;
  1417.             y = pointery;
  1418.             stamp = brush;
  1419.             updatesquare(lastx, lasty);
  1420.         }
  1421.         else if (leftdown && pointerx == GADGETX &&
  1422.         (pointery == GOLDGADGET
  1423.         || pointery == SILVERGADGET
  1424.         || pointery == EMPTYGADGET
  1425.         || pointery == WOODGADGET
  1426.         || pointery == STONEGADGET
  1427.         || pointery == METALGADGET
  1428.         || pointery == ONEGADGET
  1429.         || pointery == TWOGADGET
  1430.         || pointery == STARTGADGET))
  1431.         {    switch (pointery)
  1432.             {
  1433.             case GOLDGADGET:
  1434.                 setbrush(GOLD);
  1435.                 break;
  1436.             case SILVERGADGET:
  1437.                 setbrush(SILVER);
  1438.                 break;
  1439.             case EMPTYGADGET:
  1440.                 setbrush(EMPTY);
  1441.                 break;
  1442.             case WOODGADGET:
  1443.                 setbrush(WOOD);
  1444.                 break;
  1445.             case STONEGADGET:
  1446.                 setbrush(STONE);
  1447.                 break;
  1448.             case METALGADGET:
  1449.                 setbrush(METAL);
  1450.                 break;
  1451.             case ONEGADGET:
  1452.                 setbrush(ONE);
  1453.                 break;
  1454.             case TWOGADGET:
  1455.                 setbrush(TWO);
  1456.                 break;
  1457.             case STARTGADGET:
  1458.                 setbrush(START);
  1459.                 break;
  1460.             default:
  1461.                 break;
  1462.     }    }    }
  1463.  
  1464.     if (stamp != NOSQUARE)
  1465.     {    if (stamp == START && board[level][x][y] != TELEPORT)
  1466.         {    if (x != startx[level] || y != starty[level])
  1467.             {    draw(startx[level], starty[level], EMPTY);
  1468.                 board[level][startx[level]][starty[level]] = EMPTY;
  1469.                 draw(x, y, START);
  1470.                 startx[level] = x;
  1471.                 starty[level] = y;
  1472.                 modified = TRUE;
  1473.                 clearthem = TRUE;
  1474.         }    }
  1475.         else if (x != startx[level] || y != starty[level])
  1476.         {    if (stamp == ONE || stamp == TWO)
  1477.             {    if (teleport[level][partner(stamp - ONE)].alive == FALSE || x != teleport[level][partner(stamp - ONE)].x || y != teleport[level][partner(stamp - ONE)].y)
  1478.                 {    if (teleport[level][stamp - ONE].alive == TRUE)
  1479.                     {    draw(teleport[level][stamp - ONE].x, teleport[level][stamp - ONE].y, EMPTY);
  1480.                         board[level][teleport[level][stamp - ONE].x][teleport[level][stamp - ONE].y] = EMPTY;
  1481.                     } else
  1482.                         teleport[level][stamp - ONE].alive = TRUE;
  1483.                     board[level][x][y] = TELEPORT;
  1484.                     draw(x, y, stamp);
  1485.                     teleport[level][stamp - ONE].x = x;
  1486.                     teleport[level][stamp - ONE].y = y;
  1487.                     modified = TRUE;
  1488.                     clearthem = TRUE;
  1489.             }    }
  1490.             else
  1491.             {    if (board[level][x][y] == TELEPORT)
  1492.                     if (teleport[level][0].alive == TRUE && x == teleport[level][0].x && y == teleport[level][0].y)
  1493.                         teleport[level][0].alive = FALSE;
  1494.                     else teleport[level][1].alive = FALSE;
  1495.                 draw(x, y, stamp);
  1496.                 board[level][x][y] = stamp;
  1497.                 modified = TRUE;
  1498.                 clearthem = TRUE;
  1499. }    }    }    }
  1500.  
  1501. // exit to title screen
  1502.  
  1503. OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  1504. OffMenu(MainWindowPtr, FULLMENUNUM(MN_LEVEL, NOITEM, NOSUB));
  1505. if (timer)
  1506. {    AbortIO(TimerRqPtr);
  1507.     WaitIO(TimerRqPtr);
  1508.     timer = FALSE;
  1509. }
  1510. if (oldbrush != ANYTHING)
  1511.     brush = oldbrush;
  1512. setpointer(NORMAL);
  1513. clearstats();
  1514. if (clearthem)
  1515.     clearhiscores();
  1516. matchteleports();
  1517. iso = rememberiso;
  1518. }
  1519.  
  1520. void fileabout(void)
  1521. {    ABOOL                    done = FALSE;
  1522.     SBYTE                    line;
  1523.     UWORD                    code, qual;
  1524.     ULONG                    class;
  1525.     struct Window*            AboutWindowPtr;
  1526.     struct IntuiMessage*    MsgPtr;
  1527.     SLONG                    projectval;
  1528.     TEXT                    projectstring[6];
  1529.  
  1530.     effect(FXAMIGAN);
  1531.     if (!(AboutWindowPtr = (struct Window *) OpenWindowTags(NULL,
  1532.     WA_Left,            (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
  1533.     WA_Top,                (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
  1534.     WA_Width,            ABOUTXPIXEL,
  1535.     WA_Height,            ABOUTYPIXEL,
  1536.     WA_IDCMP,            IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  1537.     WA_Title,            "About Worm Wars",
  1538.     WA_Gadgets,            NULL,
  1539.     WA_CustomScreen,    ScreenPtr,
  1540.     WA_DragBar,            TRUE,
  1541.     WA_CloseGadget,        TRUE,
  1542.     WA_NoCareRefresh,    TRUE,
  1543.     WA_Activate,        TRUE,
  1544.     TAG_DONE)))
  1545.     {    say("Can't open About... window!", RED);
  1546.         anykey(TRUE);
  1547.     } else
  1548.     {    // calculate project size
  1549.         
  1550.         projectval =
  1551.             10                                                         // header
  1552.         +    ((HISCORES + 1) * (7 + NAMELENGTH))                     // high scores
  1553.         +    ((levels + 1) * (8 + ((FIELDX + 1) * (FIELDY + 1))))     // level data
  1554.         +    strlen(VERSION);                                        // version string
  1555.  
  1556.         SetAPen(AboutWindowPtr->RPort, worm[rand() % 4].colour);
  1557.         RectFill(AboutWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 11, ABOUTYPIXEL - 6);
  1558.         SetAPen(AboutWindowPtr->RPort, ABOUTSHADOW);
  1559.         Move(AboutWindowPtr->RPort, 7, ABOUTYPIXEL - 5);
  1560.         Draw(AboutWindowPtr->RPort, 7, 12);
  1561.         Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 10, 12);
  1562.         SetAPen(AboutWindowPtr->RPort, ABOUTSHINE);
  1563.         Draw(AboutWindowPtr->RPort, ABOUTXPIXEL - 10, ABOUTYPIXEL - 5);
  1564.         Draw(AboutWindowPtr->RPort, 8, ABOUTYPIXEL - 5);
  1565.         SetAPen(AboutWindowPtr->RPort, BLACK);
  1566.         SetDrMd(AboutWindowPtr->RPort, JAM1);
  1567.         for (line = 0; line <= ABOUTLINES; line++)
  1568.         {    Move(AboutWindowPtr->RPort, about[line].x, about[line].y);
  1569.             Text(AboutWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
  1570.         }
  1571.         stcl_d(projectstring, projectval);
  1572.         align(projectstring, 5, ' ');
  1573.         Move(AboutWindowPtr->RPort, PROJECTX, PROJECTY);
  1574.         Text(AboutWindowPtr->RPort, projectstring, 5);
  1575.         DrawBevelBox(AboutWindowPtr->RPort, 18, 21, 49, 23, GT_VisualInfo, VisualInfoPtr);
  1576.         DrawImage(AboutWindowPtr->RPort, &About, 20, 23);
  1577.  
  1578.         while(!done)
  1579.         {    Wait(1L << AboutWindowPtr->UserPort->mp_SigBit);
  1580.             while (MsgPtr = (struct IntuiMessage *) GetMsg(AboutWindowPtr->UserPort))
  1581.             {    class = MsgPtr->Class;
  1582.                 code  = MsgPtr->Code;
  1583.                 qual  = MsgPtr->Qualifier;
  1584.                 ReplyMsg(MsgPtr);
  1585.                 switch(class)
  1586.                 {
  1587.                 case IDCMP_CLOSEWINDOW:
  1588.                     done = TRUE;
  1589.                     break;
  1590.                 case IDCMP_RAWKEY:
  1591.                        if (code == SPACEBAR || code == RETURN || code == ENTER || code == HELP)
  1592.                        done = TRUE;
  1593.                     else if (code == ESCAPE)
  1594.                         if (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1595.                         {    if (verify())
  1596.                             {   CloseWindow(AboutWindowPtr);
  1597.                                 cleanexit(EXIT_SUCCESS);
  1598.                         }    }
  1599.                         else done = TRUE;
  1600.                     break;
  1601.                 default:
  1602.                     break;
  1603.         }   }   }
  1604.         CloseWindow(AboutWindowPtr);
  1605.         clearkybd();
  1606. }    }
  1607.  
  1608. void fileopen(void)
  1609. {   TEXT temp1[81] = {"Opened "}, temp2[3], newpathname[255];
  1610.  
  1611.     strcpy(newpathname, pathname);
  1612.     if (AslRequestTags(ASLRqPtr, ASL_Hail, ASLOPENHAIL, ASL_FuncFlags, FILF_PATGAD, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
  1613.     {    strcpy(newpathname, ASLRqPtr->rf_Dir);
  1614.         AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1615.         if (loadfields(newpathname))
  1616.         {   strcpy(pathname, newpathname);
  1617.             strcat(temp1, pathname);
  1618.             strcat(temp1, " (");
  1619.             stci_d(temp2, levels);
  1620.             strcat(temp1, temp2);
  1621.             strcat(temp1, " levels).");
  1622.             say(temp1, WHITE);
  1623.             if (a == FIELDEDIT)
  1624.                 renderboard();
  1625.             else hiscores();
  1626.         } else
  1627.         {   strcpy(temp1, "Couldn't open ");
  1628.             strcat(temp1, newpathname);
  1629.             strcat(temp1, "!");
  1630.             say(temp1, WHITE);
  1631.     }   }
  1632.     if (a == GAMEOVER)
  1633.         anykey(TRUE);
  1634. }
  1635.  
  1636. void filesaveas(ABOOL flag)
  1637. {    ABOOL    cont = TRUE;
  1638.     TEXT    newpathname[255], temp1[SAYLIMIT + 1], temp2[3];
  1639.  
  1640.     // flag is TRUE for 'save as...', FALSE for 'save'.
  1641.  
  1642.     strcpy(newpathname, pathname);
  1643.     if (flag)
  1644.         if (AslRequestTags(ASLRqPtr, ASL_Hail, ASLSAVEHAIL, ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
  1645.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  1646.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1647.         } else cont = FALSE;
  1648.     if (cont)
  1649.     {    strcpy(temp1, "Saving ");
  1650.         strcat(temp1, pathname);
  1651.         strcat(temp1, "...");
  1652.         say(temp1, WHITE);
  1653.         if (savefields(newpathname))
  1654.         {   strcpy(pathname, newpathname);
  1655.             strcpy(temp1, "Saved ");
  1656.             strcat(temp1, pathname);
  1657.             strcat(temp1, " (");
  1658.             stci_d(temp2, levels);
  1659.             strcat(temp1, temp2);
  1660.             strcat(temp1, " levels).");
  1661.         } else
  1662.         {   strcpy(temp1, "Couldn't save ");
  1663.             strcat(temp1, newpathname);
  1664.             strcat(temp1, "!");
  1665.         }
  1666.         say(temp1, WHITE);
  1667.         if (a == GAMEOVER)
  1668.             anykey(TRUE);
  1669. }   }
  1670.  
  1671. void freefx(void)
  1672. {    SBYTE i;
  1673.  
  1674.     stopfx(0L);
  1675.     if (!AudioClosed)
  1676.     {    CloseDevice((struct IORequest *) AudioRqPtr[0]);
  1677.         AudioClosed = TRUE;
  1678.     }
  1679.     for (i = 0; i <= 3; i++)
  1680.     {    if (AudioRqPtr[i])
  1681.         {    DeleteIORequest(AudioRqPtr[i]);
  1682.             AudioRqPtr[i] = NULL;
  1683.         }
  1684.         if (AudioPortPtr[i])
  1685.         {    DeleteMsgPort(AudioPortPtr[i]);
  1686.             AudioPortPtr[i] = NULL;
  1687.     }    }
  1688.     if (fbase)
  1689.     {    FreeMem(fbase, fsize);
  1690.         fbase = NULL;
  1691.     }
  1692.     if (FilePtr)
  1693.     {   Close(FilePtr);
  1694.         FilePtr = NULL;
  1695. }    }
  1696.  
  1697. void gameinput(void)
  1698. {        ABOOL                    done;
  1699.         UWORD                    code, qual;
  1700.         ULONG                    class;
  1701.         struct IntuiMessage*    MsgPtr;
  1702.         SBYTE                    keyplayer, which;
  1703.  
  1704. for (which = 0; which <= NUMKEYS; which++)
  1705.     key[which].down = FALSE;
  1706.  
  1707. /* human control
  1708.  
  1709. keyboard */
  1710.  
  1711. while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  1712. {    class  = MsgPtr->Class;
  1713.     code   = MsgPtr->Code;
  1714.     qual   = MsgPtr->Qualifier;
  1715.     ReplyMsg(MsgPtr);
  1716.     if (class == IDCMP_RAWKEY && !(qual & IEQUALIFIER_REPEAT) && code < KEYUP)
  1717.     {    switch(code) {
  1718.         case M:
  1719.             toggle(M);
  1720.             break;
  1721.         case F:
  1722.             toggle(F);
  1723.             break;
  1724.         case P:
  1725.             clearkybd();
  1726.             say("Paused...press P to unpause", WHITE);
  1727.             GetSysTime(CurrentValPtr);
  1728.             done = FALSE;
  1729.             while (!done)
  1730.             {    Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  1731.                 while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  1732.                 {    class = MsgPtr->Class;
  1733.                     code  = MsgPtr->Code;
  1734.                     qual  = MsgPtr->Qualifier;
  1735.                     ReplyMsg(MsgPtr);
  1736.                     if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
  1737.                     {    if (code == ESCAPE)
  1738.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1739.                             {    if (verify())
  1740.                                     cleanexit(EXIT_SUCCESS);
  1741.                             } else
  1742.                             {    a = GAMEOVER;
  1743.                                 worm[0].lives = 0;
  1744.                                 worm[1].lives = 0;
  1745.                                 worm[2].lives = 0;
  1746.                                 worm[3].lives = 0;
  1747.                                 done = TRUE;
  1748.                         }    }
  1749.                         else if (code == M)
  1750.                             toggle(M);
  1751.                         else if (code == F)
  1752.                             toggle(F);
  1753.                         else if (code == P)
  1754.                         {    say("Unpaused", WHITE);
  1755.                             done = TRUE;
  1756.             }    }    }    }
  1757.             GetSysTime(PausedValPtr);
  1758.             SubTime(PausedValPtr, CurrentValPtr);
  1759.             AddTime(StartValPtr, PausedValPtr);
  1760.             break;
  1761.         case ESCAPE:
  1762.             if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1763.             {    if (verify())
  1764.                     cleanexit(EXIT_SUCCESS);
  1765.             } else
  1766.             {    a = GAMEOVER;
  1767.                 worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
  1768.             }
  1769.             break;
  1770.         default:
  1771.             for (which = 0; which <= NUMKEYS; which++)
  1772.                 if (code == key[which].scancode)
  1773.                     key[which].down = TRUE;
  1774.             break;
  1775.     }    }    
  1776.     else if (class == IDCMP_CLOSEWINDOW)
  1777.         cleanexit(EXIT_SUCCESS);
  1778.     else if (class == IDCMP_REFRESHWINDOW)
  1779.     {   GT_BeginRefresh(MainWindowPtr);
  1780.         GT_EndRefresh(MainWindowPtr, TRUE);
  1781. }   }
  1782. /* other IDCMP messages we receive but ignore are: IDCMP_ACTIVEWINDOW,
  1783. IDCMP_MOUSEBUTTONS, IDCMP_INTUITICKS. */
  1784.  
  1785. for (which = 0; which <= NUMKEYS; which++)
  1786. {    if (key[which].down)
  1787.     {    if (key[which].special == ONEHUMAN)
  1788.         {    if (worm[0].control == HUMAN && worm[1].control != HUMAN)
  1789.                 queue(0, key[which].deltax, key[which].deltay);
  1790.             else if (worm[0].control != HUMAN && worm[1].control == HUMAN)
  1791.                 queue(1, key[which].deltax, key[which].deltay);
  1792.         } else if (key[which].special == MOVE || key[which].special == AMMO)
  1793.         {   if (worm[key[which].player].control == HUMAN)
  1794.                 keyplayer = key[which].player;
  1795.             else if (key[which].player == 1 && worm[0].control == HUMAN && worm[1].control != HUMAN)
  1796.                 keyplayer = 0;
  1797.             else if (key[which].player == 0 && worm[1].control == HUMAN && worm[0].control != HUMAN)
  1798.                 keyplayer = 1;
  1799.             else keyplayer = -1;
  1800.             if (keyplayer != -1)
  1801.                 queue(keyplayer, key[which].deltax, key[which].deltay);
  1802.         } else if (worm[1].lives > 0) // assumes key[which].special == TRAINER
  1803.             train(key[which].scancode);
  1804. }    }
  1805.  
  1806. // joysticks
  1807.  
  1808. if (worm[2].control == HUMAN)
  1809.     while (GetMsg(JoyPortPtr))
  1810.     {    if (GameEvent.ie_position.ie_xy.ie_x != 0 || GameEvent.ie_position.ie_xy.ie_y != 0)
  1811.             queue(2, GameEvent.ie_position.ie_xy.ie_x, GameEvent.ie_position.ie_xy.ie_y);
  1812.         if (GameEvent.ie_Code == IECODE_LBUTTON)
  1813.             queue(2, 0, 0);
  1814.         sendreadrequest();
  1815. }    }
  1816.  
  1817. void hiscores(void)
  1818. {    SBYTE                    which;
  1819.     TEXT                    tempstring[NAMELENGTH + 1];
  1820.  
  1821. /* render hiscores
  1822.  
  1823. darkdarkdarkdarkdarkdarkdarkdarkdark
  1824. a   a   a   a                      w
  1825. r   r   r   r                      h
  1826. k   k   k   k                      i
  1827. |   |   |   |                      t
  1828. whitewhitewhitewhitewhitewhitewhitee */
  1829.  
  1830. SetDrMd(MainWindowPtr->RPort, JAM1);
  1831. for (which = 0; which <= HISCORES; which++)
  1832. {    if (hiscore[which].player == -1)
  1833.         SetAPen(MainWindowPtr->RPort, LIGHTGREY);
  1834.     else SetAPen(MainWindowPtr->RPort, worm[hiscore[which].player].colour);
  1835.     RectFill(MainWindowPtr->RPort, 159, 105 + which * HISCOREDISTANCE, 481, 114 + which * HISCOREDISTANCE);
  1836.     if (hiscore[which].player == 0)
  1837.         SetAPen(MainWindowPtr->RPort, DARKGREEN);
  1838.     else if (hiscore[which].player == 1)
  1839.         SetAPen(MainWindowPtr->RPort, DARKRED);
  1840.     else if (hiscore[which].player == 2)
  1841.         SetAPen(MainWindowPtr->RPort, DARKBLUE);
  1842.     else if (hiscore[which].player == 3)
  1843.         SetAPen(MainWindowPtr->RPort, DARKYELLOW);
  1844.     else SetAPen(MainWindowPtr->RPort, DARKGREY);
  1845.     Move(MainWindowPtr->RPort, 158, 115 + which * HISCOREDISTANCE);
  1846.     Draw(MainWindowPtr->RPort, 158, 104 + which * HISCOREDISTANCE);
  1847.     Draw(MainWindowPtr->RPort, 482, 104 + which * HISCOREDISTANCE);
  1848.  
  1849.     if (hiscore[which].player != -1)
  1850.     {    // divider bars
  1851.     
  1852.         Move(MainWindowPtr->RPort, 182, 104 + which * HISCOREDISTANCE);
  1853.         Draw(MainWindowPtr->RPort, 182, 114 + which * HISCOREDISTANCE);
  1854.         Move(MainWindowPtr->RPort, 254, 104 + which * HISCOREDISTANCE);
  1855.         Draw(MainWindowPtr->RPort, 254, 114 + which * HISCOREDISTANCE);
  1856.         Move(MainWindowPtr->RPort, 290, 104 + which * HISCOREDISTANCE);
  1857.         Draw(MainWindowPtr->RPort, 290, 114 + which * HISCOREDISTANCE);
  1858.     }
  1859.     
  1860.     SetAPen(MainWindowPtr->RPort, WHITE);
  1861.     Move(MainWindowPtr->RPort, 159, 115 + which * HISCOREDISTANCE);
  1862.     Draw(MainWindowPtr->RPort, 482, 115 + which * HISCOREDISTANCE);
  1863.     Draw(MainWindowPtr->RPort, 482, 105 + which * HISCOREDISTANCE);
  1864.     SetAPen(MainWindowPtr->RPort, BLACK);
  1865.  
  1866.     if (hiscore[which].player != -1)
  1867.     {    stci_d(tempstring, which + 1);
  1868.         tempstring[1] = '.';
  1869.         Move(MainWindowPtr->RPort, 161, 112 + which * HISCOREDISTANCE);
  1870.         Text(MainWindowPtr->RPort, tempstring, 2);
  1871.         stci_d(tempstring, hiscore[which].score);
  1872.         align(tempstring, 7, ' ');
  1873.         Move(MainWindowPtr->RPort, 193, 112 + which * HISCOREDISTANCE);
  1874.         Text(MainWindowPtr->RPort, tempstring, 7);
  1875.         if (hiscore[which].level == -1)
  1876.             strcpy(tempstring, "All");
  1877.         else
  1878.         {    stci_d(tempstring, hiscore[which].level);
  1879.             align(tempstring, 3, ' ');
  1880.         }
  1881.         Move(MainWindowPtr->RPort, 261, 112 + which * HISCOREDISTANCE);
  1882.         Text(MainWindowPtr->RPort, tempstring, 3);
  1883.         Move(MainWindowPtr->RPort, 296, 112 + which * HISCOREDISTANCE);
  1884.         Text(MainWindowPtr->RPort, hiscore[which].name, strlen(hiscore[which].name));
  1885. }    }
  1886. SetDrMd(MainWindowPtr->RPort, JAM2);
  1887. }
  1888.  
  1889. void hiscorenames(void)
  1890. {
  1891. ULONG                    class;
  1892. ABOOL                    done;
  1893. SBYTE                    which;
  1894. struct IntuiMessage*    MsgPtr;
  1895.  
  1896. for (which = 0; which <= HISCORES; which++)
  1897.     if (hiscore[which].fresh)
  1898.     {    GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, FALSE, GTST_String, worm[hiscore[which].player].name, TAG_DONE);
  1899.         ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
  1900.         done = FALSE;
  1901.         while (!done)
  1902.         {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  1903.             {    class = MsgPtr->Class;
  1904.                 GT_ReplyIMsg(MsgPtr);
  1905.                 if (class == IDCMP_GADGETUP)
  1906.                     done = TRUE;
  1907.                 else if (class == IDCMP_MOUSEBUTTONS)
  1908.                     ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
  1909.                 else if (class == IDCMP_REFRESHWINDOW)
  1910.                 {    GT_BeginRefresh(MainWindowPtr);
  1911.                     GT_EndRefresh(MainWindowPtr, TRUE);
  1912.         }    }    }
  1913.         GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  1914.         effect(FXHISCORE);
  1915.         strcpy(hiscore[which].name, ((struct StringInfo *) (StringGadgetPtr[which]->SpecialInfo))->Buffer);
  1916.         if (hiscore[which].name[0] >= 97 && hiscore[which].name[0] <= 123)
  1917.             hiscore[which].name[0] -= 32;
  1918.         strcpy(worm[hiscore[which].player].name, hiscore[which].name);
  1919.         hiscore[which].fresh = FALSE;
  1920.         hiscores();
  1921. }    }
  1922.  
  1923. ABOOL beginfx(void)
  1924. {           SBYTE    i;
  1925.     PERSIST    UBYTE    chan[]    = {15};
  1926.  
  1927.     for (i = 0; i <= 3; i++)
  1928.     {   eversent[i] = FALSE;
  1929.         if (!(AudioPortPtr[i] = (struct MsgPort *) CreateMsgPort()))
  1930.         {   freefx();
  1931.             draw(MUSICICON, ICONY, BLACKENED);
  1932.             mode = FALSE;
  1933.             say("No port for effects!", RED);
  1934.             anykey(TRUE);
  1935.             return FALSE;
  1936.         } else if (!(AudioRqPtr[i] = (struct IOAudio *) CreateIORequest(AudioPortPtr[i], sizeof(struct IOAudio))))
  1937.         {   freefx();
  1938.             draw(MUSICICON, ICONY, BLACKENED);
  1939.             mode = FALSE;
  1940.             say("No I/O memory for effects!", RED);
  1941.             anykey(TRUE);
  1942.             return FALSE;
  1943.     }   }
  1944.     AudioRqPtr[0]->ioa_Request.io_Message.mn_ReplyPort      = AudioPortPtr[0];
  1945.     AudioRqPtr[0]->ioa_Request.io_Message.mn_Node.ln_Pri    = 127;
  1946.     AudioRqPtr[0]->ioa_AllocKey                             = 0;
  1947.     AudioRqPtr[0]->ioa_Data                                 = chan;
  1948.     AudioRqPtr[0]->ioa_Length                               = 1;
  1949.     if (AudioClosed = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioRqPtr[0], 0L))
  1950.     {   freefx();
  1951.         draw(MUSICICON, ICONY, BLACKENED);
  1952.         mode = FALSE;
  1953.         say("Can't allocate all channels for effects!", RED);
  1954.         anykey(TRUE);
  1955.         return FALSE;
  1956.     } else
  1957.     {   for (i = 1; i <= 3; i++)
  1958.             CopyMem(AudioRqPtr[0], AudioRqPtr[i], sizeof(struct IOAudio));
  1959.         return TRUE;
  1960. }   }
  1961.  
  1962. /* WormWars 4.4 .fset/.FST format for fieldset contents and high
  1963. score table (Amiga and IBM-PC), as follows:
  1964.  
  1965. header
  1966.     TEXT[]                "FSET 4.4" (NULL-terminated)
  1967.     SBYTE                levels;
  1968. high score table
  1969.     for (slot = 0; slot <= HISCORES; slot++)
  1970.     {    SBYTE            hiscore[slot].player,
  1971.                         hiscore[slot].level;
  1972.         SLONG            hiscore[slot].score;
  1973.         TEXT[]            hiscore[slot].name (NULL-terminated)
  1974.     }
  1975. level data
  1976.     for (level = 0; level <= levels; level++)
  1977.     {    SBYTE            startx[level],
  1978.                         starty[level];
  1979.         ABOOL            teleport[level][0].alive;
  1980.         SBYTE            teleport[level][0].x,
  1981.                         teleport[level][0].y;
  1982.         ABOOL            teleport[level][1].alive;
  1983.         SBYTE            teleport[level][1].x,
  1984.                         teleport[level][1].y;
  1985.         for (x = 0; x <= FIELDX; x++)
  1986.             for (y = 0; y <= FIELDY; y++)
  1987.                 SBYTE    board[level][x][y];
  1988.     }
  1989. version string
  1990.     TEXT[]                "$VER: Worm Wars 4.4 (dd.mm.yy) $" (NULL-terminated) */
  1991.  
  1992. void resettime(void)
  1993. {    GetSysTime(StartValPtr);
  1994. }
  1995.  
  1996. void rundown(SBYTE player)
  1997. {    TEXT    tempstring[6];
  1998.     SBYTE    i, j, x, y;
  1999.     UWORD    counter = 0;
  2000.  
  2001.     effect(FXENDOFLEVEL);
  2002.     SetAPen(MainWindowPtr->RPort, BLACK);
  2003.     if (iso)
  2004.         RectFill(MainWindowPtr->RPort, 0, 0, 639, 255);
  2005.     else RectFill(MainWindowPtr->RPort, STARTXPIXEL, STARTYPIXEL, ENDXPIXEL, ENDYPIXEL);
  2006.     clearstats();
  2007.     SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2008.  
  2009.     Image.ImageData = ImageData[TREASURE];
  2010.     DrawImage(MainWindowPtr->RPort, &Image, 201, 103);
  2011.     Move(MainWindowPtr->RPort, 218, 108);
  2012.     Text(MainWindowPtr->RPort, "Level Bonus:    ## x #00 =", 26);
  2013.     stci_d(tempstring, worm[player].multi);
  2014.     Move(MainWindowPtr->RPort, 218 + (FONTX * 21), 108);
  2015.     Text(MainWindowPtr->RPort, tempstring, 1);
  2016.     stci_d(tempstring, level - 1);
  2017.     align(tempstring, 2, ' ');
  2018.     Move(MainWindowPtr->RPort, 218 + (FONTX * 16), 108);
  2019.     Text(MainWindowPtr->RPort, tempstring, 2);
  2020.     stci_d(tempstring, (level - 1) * 100 * worm[player].multi);
  2021.     align(tempstring, 5, ' ');
  2022.     Move(MainWindowPtr->RPort, 218 + (FONTX * 27), 108);
  2023.     Text(MainWindowPtr->RPort, tempstring, 5);
  2024.  
  2025.     Image.ImageData = ImageData[CLOCK];
  2026.     DrawImage(MainWindowPtr->RPort, &Image, 201, 111);
  2027.     Move(MainWindowPtr->RPort, 226, 116);
  2028.     Text(MainWindowPtr->RPort,  "Time Bonus: ##:## x  #0 =", 25);
  2029.     stci_d(tempstring, worm[player].multi);
  2030.     Move(MainWindowPtr->RPort, 226 + (FONTX     * 21), 116);
  2031.     Text(MainWindowPtr->RPort, tempstring, 1);
  2032.     stci_d(tempstring, secondsleft / 60);
  2033.     align(tempstring, 2, ' ');
  2034.     Move(MainWindowPtr->RPort, 226 + (FONTX * 12), 116);
  2035.     Text(MainWindowPtr->RPort, tempstring, 2);
  2036.     stci_d(tempstring, secondsleft % 60);
  2037.     align(tempstring, 2, '0');
  2038.     Move(MainWindowPtr->RPort, 226 + (FONTX * 15), 116);
  2039.     Text(MainWindowPtr->RPort, tempstring, 2);
  2040.     stci_d(tempstring, secondsleft * 10 * worm[player].multi);
  2041.     align(tempstring, 5, ' ');
  2042.     Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 116);
  2043.     Text(MainWindowPtr->RPort, tempstring, 5);
  2044.  
  2045.     Image.ImageData = ImageData[FIRSTTAIL + player];
  2046.     DrawImage(MainWindowPtr->RPort, &Image, 201, 119);
  2047.     Move(MainWindowPtr->RPort, 226, 124);
  2048.     Text(MainWindowPtr->RPort,  "Tail Bonus:  #### x   # =", 25);
  2049.     stci_d(tempstring, worm[player].multi);
  2050.     Move(MainWindowPtr->RPort, 226 + (FONTX * 22), 124);
  2051.     Text(MainWindowPtr->RPort, tempstring, 1);
  2052.     for (x = 0; x <= FIELDX; x++)
  2053.         for (y = 0; y <= FIELDY; y++)
  2054.             if (field[x][y] == FIRSTTAIL + player)
  2055.                 counter++;
  2056.     stci_d(tempstring, counter);
  2057.     align(tempstring, 4, ' ');
  2058.     Move(MainWindowPtr->RPort, 226 + (FONTX * 13), 124);
  2059.     Text(MainWindowPtr->RPort, tempstring, 4);
  2060.     stci_d(tempstring, counter * worm[player].multi);
  2061.     align(tempstring, 5, ' ');
  2062.     Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 124);
  2063.     Text(MainWindowPtr->RPort, tempstring, 5);
  2064.  
  2065.     wormscore(player,    ((level - 1)    * 100) +
  2066.                          (secondsleft    * 10) +
  2067.                           counter);
  2068.  
  2069.     for (i = lo; i <= hi; i++)
  2070.         if (worm[i].control != NONE)
  2071.             for (j = 0; j <= LASTOBJECT; j++)
  2072.                 stat(i, j);
  2073.  
  2074.     waitasec();
  2075.     anykey(FALSE);
  2076. }
  2077.  
  2078. void say(STRPTR sentence, COLOUR colour)
  2079. {    PERSIST SBYTE length = 0;
  2080.  
  2081.     SetAPen(MainWindowPtr->RPort, BLACK);
  2082.     RectFill(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - ((length * FONTX) / 2), 1, (SCREENXPIXEL / 2) + (length * FONTX / 2), FONTY + 1);
  2083.     SetAPen(MainWindowPtr->RPort, colour);
  2084.     length = (SBYTE) strlen(sentence);
  2085.     if (length > SAYLIMIT)
  2086.     {    *(sentence + SAYLIMIT - 1) = *(sentence + SAYLIMIT - 2) = *(sentence + SAYLIMIT - 3) = '.';
  2087.         length = SAYLIMIT;
  2088.     }
  2089.     Move(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - (length * FONTX / 2), FONTY);
  2090.     Text(MainWindowPtr->RPort, sentence, length);
  2091. }
  2092.     
  2093. void sendreadrequest(void)
  2094. {    JoyRqPtr->io_Command    = GPD_READEVENT;
  2095.     JoyRqPtr->io_Flags        = NULL;
  2096.     JoyRqPtr->io_Length        = sizeof(struct InputEvent);
  2097.     JoyRqPtr->io_Data        = (APTR) &GameEvent;
  2098.     SendIO(JoyRqPtr);
  2099. }
  2100.  
  2101. void setpointer(SBYTE pointer) {
  2102. switch (pointer) {
  2103. case GOLD:
  2104.     SetRGB4(&ScreenPtr->ViewPort, 17, 10,  8,  3);        // fill
  2105.     SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);        // shadow
  2106.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12,  2);        // shine
  2107.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2108.     break;
  2109. case SILVER:
  2110.     SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10, 10);        // fill
  2111.     SetRGB4(&ScreenPtr->ViewPort, 18,  6,  6,  6);        // shadow
  2112.     SetRGB4(&ScreenPtr->ViewPort, 19, 15, 15, 15);        // shine
  2113.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2114.     break;
  2115. case EMPTY:
  2116.     SetRGB4(&ScreenPtr->ViewPort, 17,  2,  2,  2);        // fill
  2117.     SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);        // shadow
  2118.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        // shine
  2119.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2120.     break;
  2121. case WOOD:
  2122.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        // fill
  2123.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        // shadow
  2124.     SetRGB4(&ScreenPtr->ViewPort, 19, 10,  8,  3);        // shine
  2125.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2126.     break;
  2127. case STONE:
  2128.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        // fill
  2129.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        // shadow
  2130.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        // shine
  2131.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2132.     break;
  2133. case METAL:
  2134.     SetRGB4(&ScreenPtr->ViewPort, 17,  6,  6, 15);        // fill
  2135.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3, 15);        // shadow
  2136.     SetRGB4(&ScreenPtr->ViewPort, 19, 10, 10, 10);        // shine
  2137.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2138.     break;
  2139. default:
  2140.     SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4);        // fill
  2141.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3);        // shadow
  2142.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12);        // shine
  2143.     ClearPointer(MainWindowPtr);
  2144.     break; }
  2145. }
  2146.  
  2147. void stat(SBYTE player, SBYTE line)
  2148. {    ABOOL    print = TRUE;
  2149.     SBYTE    i, len, theline;
  2150.     TEXT    output[7];
  2151.  
  2152.     strcpy(output, "      "); // 6 spaces
  2153.     switch (line)
  2154.     {
  2155.     case BONUS:
  2156.         do
  2157.         {    worm[player].oldscore += (LIFEMODULO - (worm[player].oldscore % LIFEMODULO));
  2158.             if (worm[player].score >= worm[player].oldscore)
  2159.             {    worm[player].lives++;
  2160.                 stat(player, LIFE);
  2161.             }
  2162.         } while (worm[player].score > worm[player].oldscore);
  2163.         worm[player].oldscore = worm[player].score;
  2164.         if (worm[player].multi > 1)
  2165.             SetAPen(MainWindowPtr->RPort, WHITE);
  2166.         else
  2167.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2168.         if (worm[player].score > SCORELIMIT)
  2169.             worm[player].score = SCORELIMIT;
  2170.         else
  2171.         {    stcl_d(output, worm[player].score);
  2172.             for (i = 0; i <= 5; i++)
  2173.                 if (!output[i])
  2174.                 {    output[i] = ' ';
  2175.                     break;
  2176.         }        }
  2177.         theline = 0;
  2178.         len = 6;
  2179.         break;
  2180.     case LIFE:
  2181.         if (worm[player].lives > STARTLIVES)
  2182.         {    SetAPen(MainWindowPtr->RPort, WHITE);
  2183.             if (worm[player].lives > LIVESLIMIT)
  2184.                 worm[player].lives = LIVESLIMIT;
  2185.         } else SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2186.         stci_d(output, worm[player].lives);
  2187.         for (i = 0; i <= 2; i++)
  2188.             if (!output[i])
  2189.             {    output[i] = ' ';
  2190.                 break;
  2191.             }
  2192.         theline = 1;
  2193.         len = 3;
  2194.         break;
  2195.     case BIAS:
  2196.         if (worm[player].bias > 0)
  2197.         {    if (worm[player].bias > BIASLIMIT)
  2198.                 worm[player].bias = BIASLIMIT;
  2199.             SetAPen(MainWindowPtr->RPort, WHITE);
  2200.         } else
  2201.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2202.         stci_d(output, worm[player].bias);
  2203.         for (i = 0; i <= 2; i++)
  2204.             if (!output[i])
  2205.             {    output[i] = ' ';
  2206.                 break;
  2207.             }
  2208.         theline = 2;
  2209.         len = 3;
  2210.         break;
  2211.     case NITRO:
  2212.         SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2213.         if (worm[player].speed == FAST)
  2214.             strcpy(output, STATFAST);
  2215.         else if (worm[player].speed == NORMAL)
  2216.             strcpy(output, STATNORMAL);
  2217.         else // assumes worm[player].speed == SLOW
  2218.             strcpy(output, STATSLOW);
  2219.         theline = 3;
  2220.         len = 6;
  2221.         break;
  2222.     case AMMO:
  2223.         if (worm[player].ammo)
  2224.         {    if (worm[player].ammo > AMMOLIMIT)
  2225.                 worm[player].ammo = AMMOLIMIT;
  2226.             SetAPen(MainWindowPtr->RPort, WHITE);
  2227.         } else
  2228.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2229.         stci_d(output, worm[player].ammo);
  2230.         for (i = 0; i <= 2; i++)
  2231.             if (!output[i])
  2232.             {    output[i] = ' ';
  2233.                 break;
  2234.             }
  2235.         if (iso)
  2236.             theline = 4;
  2237.         else theline = 5;
  2238.         len = 3;
  2239.         break;
  2240.     case POWER:
  2241.         switch(worm[player].power)
  2242.         {    case 0:
  2243.                 SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2244.                 strcpy(output, STATSINGLE);
  2245.                 break;
  2246.             case 2:
  2247.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2248.                 strcpy(output, STATTRIPLE);
  2249.                 break;
  2250.             case 4:
  2251.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2252.                 strcpy(output, STATQUINTUPLE);
  2253.                 break;
  2254.             case 6:
  2255.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2256.                 strcpy(output, STATSEPTUPLE);
  2257.                 break;
  2258.             default:
  2259.                 break;
  2260.         }
  2261.         if (iso)
  2262.             theline = 5;
  2263.         else theline = 6;
  2264.         len = 6;
  2265.         break;
  2266.     case ARMOUR:
  2267.         if (worm[player].armour > MODELIMIT)
  2268.             worm[player].armour = MODELIMIT;
  2269.         if (worm[player].mode == ARMOUR)
  2270.             SetAPen(MainWindowPtr->RPort, WHITE);
  2271.         else
  2272.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2273.         stci_d(output, worm[player].armour);
  2274.         for (i = 0; i <= 2; i++)
  2275.             if (!output[i])
  2276.             {    output[i] = ' ';
  2277.                 break;
  2278.             }
  2279.         if (iso)
  2280.             theline = 6;
  2281.         else theline = 8;
  2282.         len = 3;
  2283.         break;
  2284.     case TONGUE:
  2285.         if (worm[player].tongue > MODELIMIT)
  2286.             worm[player].tongue = MODELIMIT;
  2287.         if (worm[player].mode == TONGUE)
  2288.             SetAPen(MainWindowPtr->RPort, WHITE);
  2289.         else
  2290.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2291.         stci_d(output, worm[player].tongue);
  2292.         for (i = 0; i <= 2; i++)
  2293.             if (!output[i])
  2294.             {    output[i] = ' ';
  2295.                 break;
  2296.             }
  2297.         if (iso)
  2298.             theline = 7;
  2299.         else theline = 9;
  2300.         len = 3;
  2301.         break;
  2302.     default:
  2303.         print = FALSE;
  2304.         break;
  2305.     }
  2306.  
  2307.     if (print)
  2308.     {    if (iso)
  2309.             switch(player)
  2310.             {
  2311.             case 0:
  2312.                 Move(MainWindowPtr->RPort, 0  ,   9 + (theline * FONTY));
  2313.                 break;
  2314.             case 1:
  2315.                 Move(MainWindowPtr->RPort, 528, 189 + (theline * FONTY));
  2316.                 break;
  2317.             case 2:
  2318.                 Move(MainWindowPtr->RPort, 66 ,   9 + (theline * FONTY));
  2319.                 break;
  2320.             case 3:
  2321.                 Move(MainWindowPtr->RPort, 592, 189 + (theline * FONTY));
  2322.                 break;
  2323.             default:
  2324.                 // assert(0);
  2325.                 break;
  2326.             }
  2327.         else
  2328.         {    Move
  2329.             (    MainWindowPtr->RPort,
  2330.                 (FONTX * 2) + (worm[player].statx * (ENDXPIXEL + FONTX)),
  2331.                 STARTYPIXEL + 6 + (theline * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2332.             );
  2333.         }
  2334.         Text(MainWindowPtr->RPort, output, len);
  2335. }    }
  2336.  
  2337. void stopfx(ULONG receipt)
  2338. {    SBYTE i;
  2339.  
  2340.     if (mode == FX)
  2341.         for (i = 0; i <= 3; i++)
  2342.             if (eversent[i] && (!(CheckIO(AudioRqPtr[i]))) && (receipt == 0L || receipt == receipter[i]))
  2343.             {   AbortIO(AudioRqPtr[i]);
  2344.                 WaitIO(AudioRqPtr[i]);
  2345. }           }
  2346.  
  2347. void titlescreen(void)
  2348. {    SBYTE                    lisa = 0, object = 0, player, segment = 0;
  2349.     ULONG                    class, ormw = 0;
  2350.     UWORD                    code, qual;
  2351.     struct IntuiMessage*    MsgPtr;
  2352.     struct Gadget*            WhichGadgetPtr;
  2353.     ABOOL                    rememberiso;
  2354.     struct MenuItem*        ItemPtr;
  2355.  
  2356.     effect(FXTITLESCREEN);
  2357.     draw(CLOCKICON, ICONY, BLACKENED);
  2358.     Forbid();
  2359.     MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  2360.     Permit();
  2361.     SetAPen(MainWindowPtr->RPort, BLACK);
  2362.     if (iso)
  2363.         RectFill
  2364.         (    MainWindowPtr->RPort,
  2365.             0, 0,
  2366.             639, 255
  2367.         );
  2368.     else
  2369.         RectFill
  2370.         (    MainWindowPtr->RPort,
  2371.             STARTXPIXEL, STARTYPIXEL,
  2372.             ENDXPIXEL, ENDYPIXEL
  2373.         );
  2374.     clearstats();
  2375.     rememberiso = iso;
  2376.     iso = FALSE;
  2377.  
  2378.     SetMenuStrip(MainWindowPtr, MenuPtr);
  2379.     for (player = 0; player <= 3; player++)
  2380.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  2381.     GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  2382.  
  2383.     clearkybd();
  2384.     clearjoystick();
  2385.     hiscores();
  2386.     hiscorenames();
  2387.     
  2388.     do
  2389.     {    TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  2390.         TimerRqPtr->tr_time.tv_secs        = 0;
  2391.         TimerRqPtr->tr_time.tv_micro    = ANIMDELAY;
  2392.         SendIO(TimerRqPtr);
  2393.  
  2394.         /* W     W  OOOO  RRRRR  MM   MM
  2395.            W     W O    O R    R M M M M
  2396.            W  W  W O    O RRRRR  M  M  M
  2397.            W W W W O    O R R    M     M
  2398.            WW   WW  OOOO  R  RRR M     M */
  2399.  
  2400.         if (segment == 0)
  2401.         {    worm[0].x = FIELDX / 2 - 14;
  2402.             worm[0].y = 1;
  2403.             worm[1].x = FIELDX / 2 -  5;
  2404.             worm[1].y = 1;
  2405.             worm[2].x = FIELDX / 2 +  1;
  2406.             worm[2].y = 5;
  2407.             worm[3].x = FIELDX / 2 +  8;
  2408.             worm[3].y = 5;
  2409.         }
  2410.         for (player = 0; player <= 3; player++)
  2411.             if (anim[player][segment].x != SENTINEL)
  2412.             {    draw(worm[player].x, worm[player].y, FIRSTTAIL + ((player + ormw) % 4));
  2413.                 worm[player].x += anim[player][segment].x;
  2414.                 worm[player].y += anim[player][segment].y;
  2415.                 draw(worm[player].x, worm[player].y, eachworm[(player + ormw) % 4][0][anim[player][segment].x + 1 + (anim[player][segment].y + 1) * 3]);
  2416.             }
  2417.         if (++segment > SEGMENTS)
  2418.         {    segment = 0;
  2419.             if (++ormw == 1)
  2420.             {    effect(FXSTAMPED);
  2421.                 DrawImage(MainWindowPtr->RPort, &Logo, 203, 50);
  2422.             }
  2423.             if (++object > LASTOBJECT)
  2424.                 object = 0;
  2425.             say(objectdesc[object], WHITE);
  2426.             Image.ImageData = ImageData[object];
  2427.             DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
  2428.             DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2429.         }
  2430.  
  2431.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  2432.         {    WhichGadgetPtr = (struct Gadget *) MsgPtr->IAddress;
  2433.             class = MsgPtr->Class;
  2434.             code  = MsgPtr->Code;
  2435.             qual  = MsgPtr->Qualifier;
  2436.             GT_ReplyIMsg(MsgPtr);
  2437.             switch (class) {
  2438.             case IDCMP_RAWKEY:
  2439.                 if (!(qual & IEQUALIFIER_REPEAT))
  2440.                     switch (code) {
  2441.                     case F:
  2442.                         toggle(F);
  2443.                         break;
  2444.                     case M:
  2445.                         toggle(M);
  2446.                         break;
  2447.                     case SPACEBAR:
  2448.                         effect(FXCLICK);
  2449.                         a = FIELDEDIT;
  2450.                         break;
  2451.                     case F1:
  2452.                     case ALPHAONE:
  2453.                     case NUMERICONE:
  2454.                         effect(FXCLICK);
  2455.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2456.                         {    if (--worm[0].control < 0)
  2457.                                 worm[0].control = 2;
  2458.                         } else
  2459.                         {    if (++worm[0].control > 2)
  2460.                                 worm[0].control = 0;
  2461.                         }
  2462.                         GT_SetGadgetAttrs(CycleGadgetPtr[0], MainWindowPtr, NULL, GTCY_Active, worm[0].control, TAG_DONE);
  2463.                         break;
  2464.                     case F2:
  2465.                     case ALPHATWO:
  2466.                     case NUMERICTWO:
  2467.                         effect(FXCLICK);
  2468.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2469.                         {    if (--worm[1].control < 0)
  2470.                                 worm[1].control = 2;
  2471.                         } else
  2472.                         {    if (++worm[1].control > 2)
  2473.                                 worm[1].control = 0;
  2474.                         }
  2475.                         GT_SetGadgetAttrs(CycleGadgetPtr[1], MainWindowPtr, NULL, GTCY_Active, worm[1].control, TAG_DONE);
  2476.                         break;
  2477.                     case F3:
  2478.                     case ALPHATHREE:
  2479.                     case NUMERICTHREE:
  2480.                         effect(FXCLICK);
  2481.                         if (joy)
  2482.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2483.                             {    if (--worm[2].control < 0)
  2484.                                     worm[2].control = 2;
  2485.                             } else
  2486.                             {    if (++worm[2].control > 2)
  2487.                                     worm[2].control = 0;
  2488.                         }    }
  2489.                         else if (worm[2].control == NONE)
  2490.                             worm[2].control = AMIGA;
  2491.                         else
  2492.                             worm[2].control = NONE;
  2493.                         GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2494.                         break;
  2495.                     case F4:
  2496.                     case ALPHAFOUR:
  2497.                     case NUMERICFOUR:
  2498.                         effect(FXCLICK);
  2499.                         if (worm[3].control == NONE)
  2500.                             worm[3].control = AMIGA;
  2501.                         else
  2502.                             worm[3].control = NONE;
  2503.                         GT_SetGadgetAttrs(CycleGadgetPtr[3], MainWindowPtr, NULL, GTCY_Active, worm[3].control, TAG_DONE);
  2504.                         break;
  2505.                     case RETURN:
  2506.                     case ENTER:
  2507.                         a = PLAYGAME;
  2508.                         break;
  2509.                     case I:
  2510.                         effect(FXCLICK);
  2511.                         rememberiso = !rememberiso;
  2512.                         GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GTCB_Checked, rememberiso, TAG_DONE);
  2513.                         break;                    
  2514.                     case ESCAPE:
  2515.                         if (verify())
  2516.                             cleanexit(EXIT_SUCCESS);
  2517.                         break;
  2518.                     case HELP:
  2519.                         fileabout();
  2520.                         break;
  2521.                     case INTERNATIONALONE:
  2522.                         if (lisa == 2)
  2523.                         {    say(FIRSTLISA, RED);
  2524.                             anykey(FALSE);
  2525.                             lisa = 0;
  2526.                         } else
  2527.                             lisa = 1;
  2528.                         break;
  2529.                     case INTERNATIONALTWO:
  2530.                         if (lisa == 1)
  2531.                         {    say(SECONDLISA, BLUE);
  2532.                             anykey(FALSE);
  2533.                             lisa = 0;
  2534.                         } else
  2535.                             lisa = 2;
  2536.                         break;
  2537.                     default:
  2538.                         break;
  2539.                     }
  2540.                 break;
  2541.             case IDCMP_MENUPICK:
  2542.                 while (code != MENUNULL)
  2543.                 {    ItemPtr = ItemAddress(MenuPtr, code);
  2544.                     switch (MENUNUM(code))
  2545.                     {
  2546.                     case MN_PROJECT:
  2547.                         switch (ITEMNUM(code))
  2548.                         {
  2549.                         case IN_NEW:
  2550.                             effect(FXFILENEW);
  2551.                             newfields();
  2552.                             say("New done.", WHITE);
  2553.                             anykey(TRUE);
  2554.                             say(objectdesc[object], WHITE);
  2555.                             break;
  2556.                         case IN_OPEN:
  2557.                             effect(FXFILEOPEN);
  2558.                             fileopen();
  2559.                             say(objectdesc[object], WHITE);
  2560.                             break;
  2561.                         case IN_SAVE:
  2562.                             effect(FXFILESAVE);
  2563.                             filesaveas(FALSE);
  2564.                             say(objectdesc[object], WHITE);
  2565.                             break;
  2566.                         case IN_SAVEAS:
  2567.                             effect(FXFILESAVEAS);
  2568.                             filesaveas(TRUE);
  2569.                             say(objectdesc[object], WHITE);
  2570.                             break;
  2571.                         case IN_ABOUT:
  2572.                             fileabout();
  2573.                             break;
  2574.                         case IN_QUIT:
  2575.                             if (verify())
  2576.                                 cleanexit(EXIT_SUCCESS);
  2577.                             break;
  2578.                         default:
  2579.                             break;
  2580.                         }
  2581.                         break;
  2582.                     default:
  2583.                         break;
  2584.                     }
  2585.                     code = ItemPtr->NextSelect;
  2586.                 }
  2587.                 break;
  2588.             case IDCMP_MOUSEBUTTONS:
  2589.                 if (code == SELECTDOWN)
  2590.                     if (ignore)
  2591.                         ignore = FALSE;
  2592.                     else a = PLAYGAME;
  2593.                 break;
  2594.             case IDCMP_REFRESHWINDOW:
  2595.                 GT_BeginRefresh(MainWindowPtr);
  2596.                 GT_EndRefresh(MainWindowPtr, TRUE);
  2597.                 break;
  2598.             case IDCMP_GADGETUP:
  2599.                 if (WhichGadgetPtr == CheckboxGadgetPtr)
  2600.                     rememberiso = !rememberiso;
  2601.                 else
  2602.                 {    for (player = 0; player <= 3; player++)
  2603.                         if (WhichGadgetPtr == CycleGadgetPtr[player])
  2604.                         {    if (code == HUMAN && player == 2 && (!joy))
  2605.                             {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2606.                                     worm[2].control = NONE;
  2607.                                 else
  2608.                                     worm[2].control = AMIGA;
  2609.                                 GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2610.                             } else
  2611.                                 worm[player].control = code;
  2612.                             break;
  2613.                         }
  2614.                 }
  2615.                 break;
  2616.             case IDCMP_ACTIVEWINDOW:
  2617.                 ignore = TRUE;
  2618.                 break;
  2619.             case IDCMP_CLOSEWINDOW:
  2620.                 cleanexit(EXIT_SUCCESS);
  2621.                 break;
  2622.             default:
  2623.                 // IDCMP_MENUVERIFY, IDCMP_INTUITICKS
  2624.                 break;
  2625.         }    }
  2626.         if (joy && GetMsg(JoyPortPtr))
  2627.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  2628.                 a = PLAYGAME;
  2629.             sendreadrequest();
  2630.         }
  2631.         if (a == PLAYGAME)
  2632.         {    if (worm[0].control == NONE && worm[1].control == NONE && worm[2].control == NONE && worm[3].control == NONE)
  2633.             {    say("No worms active!", WHITE);
  2634.                 anykey(TRUE);
  2635.                 a = GAMEOVER;
  2636.         }    }
  2637.         if (CheckIO(TimerRqPtr))
  2638.             draw(CLOCKICON, ICONY, CLOCK);
  2639.         else draw(CLOCKICON, ICONY, BLACKENED);
  2640.         WaitIO(TimerRqPtr);
  2641.     } while (a == GAMEOVER);
  2642.  
  2643.     for (player = 0; player <= 3; player++)
  2644.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2645.     GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2646.     Image.ImageData = ImageData[BLACKENED];
  2647.     DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
  2648.     DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2649.     if (a == FIELDEDIT)
  2650.         fieldedit();
  2651.     else
  2652.     {    iso = rememberiso;
  2653.         newgame();
  2654.         if (!iso)
  2655.         {    for (player = lo; player <= hi; player++)
  2656.             {    if (worm[player].control != NONE)
  2657.                 {    Image.ImageData = ImageData[BONUS];
  2658.                     DrawImage
  2659.                     (    MainWindowPtr->RPort,
  2660.                         &Image,
  2661.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2662.                         STARTYPIXEL + 1               + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2663.                     );
  2664.                     Image.ImageData = ImageData[LIFE];
  2665.                     DrawImage
  2666.                     (    MainWindowPtr->RPort,
  2667.                         &Image,
  2668.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2669.                         STARTYPIXEL + 1 + (1 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2670.                     );
  2671.                     Image.ImageData = ImageData[BIAS];
  2672.                     DrawImage
  2673.                     (    MainWindowPtr->RPort,
  2674.                         &Image,
  2675.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2676.                         STARTYPIXEL + 1 + (2 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2677.                     );
  2678.                     Image.ImageData = ImageData[NITRO];
  2679.                     DrawImage
  2680.                     (    MainWindowPtr->RPort,
  2681.                         &Image,
  2682.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2683.                         STARTYPIXEL + 1 + (3 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2684.                     );
  2685.                     Image.ImageData = ImageData[AMMO];
  2686.                     DrawImage
  2687.                     (    MainWindowPtr->RPort,
  2688.                         &Image,
  2689.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2690.                         STARTYPIXEL + 1 + (5 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2691.                     );
  2692.                     Image.ImageData = ImageData[POWER];
  2693.                     DrawImage
  2694.                     (    MainWindowPtr->RPort,
  2695.                         &Image,
  2696.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2697.                         STARTYPIXEL + 1 + (6 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2698.                     );
  2699.                     Image.ImageData = ImageData[ARMOUR];
  2700.                     DrawImage
  2701.                     (    MainWindowPtr->RPort,
  2702.                         &Image,
  2703.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2704.                         STARTYPIXEL + 1 + (8 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2705.                     );
  2706.                     Image.ImageData = ImageData[TONGUE];
  2707.                     DrawImage
  2708.                     (    MainWindowPtr->RPort,
  2709.                         &Image,
  2710.                         worm[player].statx * (ENDXPIXEL + FONTX),
  2711.                         STARTYPIXEL + 1 + (9 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2712.                     );
  2713.         }    }    }
  2714.         else // assert (iso);
  2715.         {    if (worm[0].control != NONE || worm[2].control != NONE)
  2716.             {    Image.ImageData = ImageData[BONUS];
  2717.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 4);
  2718.                 Image.ImageData = ImageData[LIFE];
  2719.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 12);
  2720.                 Image.ImageData = ImageData[BIAS];
  2721.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 20);
  2722.                 Image.ImageData = ImageData[NITRO];
  2723.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 28);
  2724.                 Image.ImageData = ImageData[AMMO];
  2725.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 36);
  2726.                 Image.ImageData = ImageData[POWER];
  2727.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 44);
  2728.                 Image.ImageData = ImageData[ARMOUR];
  2729.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 52);
  2730.                 Image.ImageData = ImageData[TONGUE];
  2731.                 DrawImage(MainWindowPtr->RPort, &Image, 54, 60);
  2732.             }
  2733.             if (worm[1].control != NONE || worm[3].control != NONE)
  2734.             {    Image.ImageData = ImageData[BONUS];
  2735.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 183);
  2736.                 Image.ImageData = ImageData[LIFE];
  2737.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 191);
  2738.                 Image.ImageData = ImageData[BIAS];
  2739.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 199);
  2740.                 Image.ImageData = ImageData[NITRO];
  2741.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 207);
  2742.                 Image.ImageData = ImageData[AMMO];
  2743.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 215);
  2744.                 Image.ImageData = ImageData[POWER];
  2745.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 223);
  2746.                 Image.ImageData = ImageData[ARMOUR];
  2747.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 231);
  2748.                 Image.ImageData = ImageData[TONGUE];
  2749.                 DrawImage(MainWindowPtr->RPort, &Image, 579, 239);
  2750.         }    }
  2751.         clearkybd();
  2752.         Forbid();
  2753.         MainWindowPtr->Flags |= WFLG_RMBTRAP;
  2754.         Permit();
  2755. }    }
  2756.  
  2757. void toggle(SBYTE key)
  2758. {    PERSIST ABOOL songstarted = FALSE;
  2759.  
  2760.     switch(key)
  2761.     {
  2762.     case F:
  2763.         if (mode == FX)                    // F in FX mode: no sound
  2764.         {    freefx();
  2765.             mode = FALSE;
  2766.             draw(MUSICICON, ICONY, BLACKENED);
  2767.         } else if (fxable > 0)            // F otherwise: change to FX mode
  2768.         {    if (mode == MUSIC)            // stop any music that is playing
  2769.             {    StopPlayer();
  2770.                 FreePlayer();
  2771.             }
  2772.             if (fxable == 3)            // load samples if needed
  2773.                 loadthefx();
  2774.             if (fxable == 1)            // if we have samples in memory
  2775.             {    if (beginfx())
  2776.                 {    mode = FX;
  2777.                     effect(FXFX);
  2778.                     draw(MUSICICON, ICONY, FX);
  2779.         }    }    }
  2780.         break;
  2781.     case M:
  2782.         if (mode == MUSIC)                // M in MUSIC mode: no sound
  2783.         {    StopPlayer();
  2784.             FreePlayer();
  2785.             mode = FALSE;
  2786.             draw(MUSICICON, ICONY, BLACKENED);
  2787.         } else if (musicable > 0)        // M otherwise: change to music mode
  2788.         {    if (mode == FX)                // stop any samples that are playing
  2789.                 freefx();
  2790.             if (musicable == 3)
  2791.                 loadthemusic();
  2792.             if (musicable == 1)
  2793.             {    if (GetPlayer(0))
  2794.                 {    say("No channels for music!", RED);
  2795.                     anykey(TRUE);
  2796.                     mode = FALSE;
  2797.                     draw(MUSICICON, ICONY, BLACKENED);
  2798.                 } else
  2799.                 {    if (songstarted)
  2800.                         ContModule(SongPtr);
  2801.                     else
  2802.                     {    PlayModule(SongPtr);
  2803.                         songstarted = TRUE;
  2804.                     }
  2805.                     mode = MUSIC;
  2806.                     draw(MUSICICON, ICONY, MUSIC);
  2807.         }    }    }
  2808.         break;
  2809.     default:
  2810.         break;
  2811. }    }
  2812.     
  2813. void underline(SBYTE square)
  2814. {    /* Removes old underline, draws new underline.
  2815.     
  2816.     square: which square-type to underline, or -1 for clear only.
  2817.     Squares which do not correspond to any pseudo-gadgets
  2818.     (eg. objects) are converted to -1s. */
  2819.  
  2820. PERSIST    SWORD oldy = -1;
  2821.         SWORD y;
  2822.  
  2823.     switch(square)
  2824.     {
  2825.     case GOLD:
  2826.         y = UNDERLINEOFFSET;
  2827.         break;
  2828.     case SILVER:
  2829.         y = UNDERLINEOFFSET + (SQUAREY *  3);
  2830.         break;
  2831.     case EMPTY:
  2832.         y = UNDERLINEOFFSET + (SQUAREY *  6);
  2833.         break;
  2834.     case WOOD:
  2835.         y = UNDERLINEOFFSET + (SQUAREY *  9);
  2836.         break;
  2837.     case STONE:
  2838.         y = UNDERLINEOFFSET + (SQUAREY * 12);
  2839.         break;
  2840.     case METAL:
  2841.         y = UNDERLINEOFFSET + (SQUAREY * 15);
  2842.         break;
  2843.     case ONE:
  2844.         y = UNDERLINEOFFSET + (SQUAREY * 18);
  2845.         break;
  2846.     case TWO:
  2847.         y = UNDERLINEOFFSET + (SQUAREY * 21);
  2848.         break;
  2849.     case START:
  2850.         y = UNDERLINEOFFSET + (SQUAREY * 24);
  2851.         break;
  2852.     default:
  2853.         square = -1;
  2854.         break;
  2855.     }
  2856.  
  2857.     if (oldy != -1)
  2858.     {    SetAPen(MainWindowPtr->RPort, BLACK);
  2859.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy);
  2860.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy + SQUAREY + 3);
  2861.     }
  2862.     if (square != -1)
  2863.     {    SetAPen(MainWindowPtr->RPort, WHITE);
  2864.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y);
  2865.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y + SQUAREY + 3);
  2866.         oldy = y;
  2867. }    }
  2868.  
  2869. ABOOL verify(void)
  2870. {    if (modified && (EasyRequest(MainWindowPtr, &EasyStruct, NULL) == 0))
  2871.         return(FALSE);
  2872.     else
  2873.         return(TRUE);
  2874. }
  2875.  
  2876. void waitasec(void)
  2877. {   Delay(50);
  2878. }
  2879.  
  2880. void systemsetup(void)
  2881. {    worm[0].control    = NONE;
  2882.     worm[1].control    = HUMAN;
  2883.     worm[2].control    = NONE;
  2884.     worm[3].control = AMIGA;
  2885. }
  2886.  
  2887. ABOOL ZOpen(STRPTR fieldname, ABOOL write)
  2888. {    if (!write)
  2889.         if (FilePtr = Open(fieldname, MODE_OLDFILE))
  2890.             return TRUE;
  2891.         else return FALSE;
  2892.     else
  2893.         if (FilePtr = Open(fieldname, MODE_NEWFILE))
  2894.             return TRUE;
  2895.         else return FALSE;
  2896. }
  2897. ABOOL ZRead(STRPTR IOBuffer, ULONG length)
  2898. {    if (Read(FilePtr, IOBuffer, length) == length)
  2899.         return TRUE;
  2900.     else return FALSE;
  2901. }
  2902. ABOOL ZWrite(STRPTR IOBuffer, ULONG length)
  2903. {    if (Write(FilePtr, IOBuffer, length) == length)
  2904.         return TRUE;
  2905.     else return FALSE;
  2906. }
  2907. ABOOL ZClose(void)
  2908. {    if (Close(FilePtr))
  2909.     {    FilePtr = NULL;
  2910.         return TRUE;
  2911.     } else
  2912.     {    /* "If Close() returns DOSFALSE, the user has already cancelled an
  2913.         error requester and the function has already freed the FileHandle
  2914.         (and even marked it so any attempt to close it again will bring up
  2915.         the "Software Failure" requester). Therefore FilePtr should be set
  2916.         to zero in any case." - Jilles Tjoelker. */
  2917.  
  2918.         FilePtr = NULL;
  2919.         return FALSE;
  2920. }    }
  2921.  
  2922. void timing(void)
  2923. {    ;
  2924. }
  2925.  
  2926. void loadthefx(void)
  2927. {    UBYTE*          p8data;
  2928.  
  2929.     TEXT            saystring[SAYLIMIT + 1];
  2930.  
  2931.     SBYTE           code = 0, i;
  2932.     SBYTE           iobuffer[8];        // buffer for 8SVX.VHDR 
  2933.     SBYTE*          psample[2];         // sample pointers
  2934.     struct Chunk*   p8Chunk;            // pointers for 8SVX parsing
  2935.     Voice8Header*   pVoice8Header;
  2936.     ULONG           rd8count;
  2937.  
  2938.     say("Loading sound effects...", WHITE);
  2939.     fxable = 1;
  2940.  
  2941.     for (i = 0; i <= SAMPLES; i++)
  2942.         sbase[i] = NULL;
  2943.     for (i = 0; i <= SAMPLES; i++)
  2944.     {   if (!(FilePtr = Open(samp[i].filename, MODE_OLDFILE)))
  2945.             code = 1;                               // can't open file
  2946.         else
  2947.         {   rd8count = Read(FilePtr, iobuffer, 8L);
  2948.             if (rd8count == -1)
  2949.                 code = 2;                           // can't read file
  2950.             else if (rd8count < 8)
  2951.                 code = 3;                           // not an IFF 8SVX; too short
  2952.             else
  2953.             {   p8Chunk = (struct Chunk *) iobuffer;
  2954.                 if (p8Chunk->ckID != ID_FORM)
  2955.                     code = 4;                       // not an IFF FORM
  2956.                 else if (!(fbase = (UBYTE *) AllocMem(fsize = p8Chunk->ckSize, MEMF_PUBLIC | MEMF_CLEAR)))
  2957.                     code = 5;                       // no memory for read
  2958.                 else
  2959.                 {   p8data = fbase;
  2960.                     rd8count = Read(FilePtr, p8data, p8Chunk->ckSize);
  2961.                     if (rd8count == -1)
  2962.                         code = 6;                   // read error
  2963.                     else if (rd8count < p8Chunk->ckSize)
  2964.                         code = 7;                   // malformed IFF; too short
  2965.                     else if (MAKE_ID(*p8data, *(p8data + 1), *(p8data + 2), *(p8data + 3)) != ID_8SVX)
  2966.                         code = 8;                   // not an IFF 8SVX
  2967.                     else
  2968.                     {   p8data = p8data + 4;
  2969.                         while (p8data < fbase + fsize)
  2970.                         {   p8Chunk = (struct Chunk *) p8data;
  2971.                             switch(p8Chunk->ckID) {
  2972.                             case ID_VHDR:
  2973.                                 pVoice8Header = (Voice8Header *) (p8data + 8L);
  2974.                                 break;
  2975.                             case ID_BODY:
  2976.                                 psample[0]    = (SBYTE *) (p8data + 8L);
  2977.                                 psample[1]    = psample[0] + pVoice8Header->oneShotHiSamples;
  2978.                                 length[i][0]  = (ULONG) pVoice8Header->oneShotHiSamples;
  2979.                                 length[i][1]  = (ULONG) pVoice8Header->repeatHiSamples;
  2980.  
  2981.                                 /* To grab the volume level from the IFF
  2982.                                 8SVX file itself, add this here:
  2983.  
  2984.                                 samp[i].volume  = (SBYTE) (pVoice8Header->volume / 156); */
  2985.  
  2986.                                    break;
  2987.                                default:
  2988.                                    break;
  2989.                             }
  2990.                             p8data += 8L + p8Chunk->ckSize;
  2991.                             if (p8Chunk->ckSize & 1L == 1)
  2992.                                 p8data++;
  2993.                         }
  2994.                         if (length[i][0] == 0)
  2995.                             yes[i] = 1;
  2996.                         else yes[i] = 0;
  2997.                         if (length[i][yes[i]] <= 102400)
  2998.                             ssize[i] = length[i][yes[i]];
  2999.                         else ssize[i] = 102400;
  3000.                         sbase[i] = (UBYTE *) AllocMem(ssize[i], MEMF_CHIP | MEMF_CLEAR);
  3001.                         if (!sbase[i])
  3002.                             code = 9;               // no chip memory
  3003.                         else
  3004.                         {   CopyMem(psample[yes[i]], sbase[i], ssize[i]);
  3005.                             psample[yes[i]] += ssize[i];
  3006.                             speed[i] = PALCLOCK / pVoice8Header->samplesPerSec;
  3007.                             if (fbase)
  3008.                             {   FreeMem(fbase, fsize);
  3009.                                 fbase = NULL;
  3010.                             }
  3011.                             if (FilePtr)
  3012.                             {   Close(FilePtr);
  3013.                                 FilePtr = NULL;
  3014.         }   }   }   }   }   }
  3015.         if (code)
  3016.         {   freefx();
  3017.             fxable = 0;
  3018.             strcpy(saystring, samp[i].filename);
  3019.             strcat(saystring, ": ");
  3020.             strcat(saystring, sfxerror[code]);
  3021.             say(saystring, RED);
  3022.             anykey(TRUE);
  3023.             break;
  3024. }    }   }
  3025.  
  3026. void loadthemusic(void)
  3027. {    if (!(MEDPlayerBase = (struct MEDPlayerBase *) OpenLibrary("medplayer.library", 0L)))
  3028.     {    say("Can't open MEDPlayer.library!", RED);
  3029.         anykey(TRUE);
  3030.     } else
  3031.     {    say("Loading music...", WHITE);
  3032.         if (SongPtr = (struct MMD0 *) LoadModule(MEDMODULE))
  3033.             musicable = TRUE;
  3034.         else
  3035.         {    say("Can't load music!", RED);
  3036.             anykey(TRUE);
  3037. }    }    }
  3038.  
  3039. void dot(SBYTE x, SBYTE y)
  3040. {    SWORD xx, yy;
  3041.  
  3042.     /* Squares are dotted as follows:
  3043.     
  3044.      012345678
  3045.     0.........
  3046.     1.........
  3047.     2...WWW...
  3048.     3...WWWB..
  3049.     4....BBB..
  3050.     5......... */
  3051.  
  3052.     xx = (x * SQUAREX) + STARTXPIXEL;
  3053.     yy = (y * SQUAREY) + STARTYPIXEL;
  3054.  
  3055.     SetAPen(MainWindowPtr->RPort, WHITE);
  3056.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 2);
  3057.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 2);
  3058.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 2);
  3059.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 3);
  3060.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 3);
  3061.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 3);
  3062.     SetAPen(MainWindowPtr->RPort, BLACK);
  3063.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 3);
  3064.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 4);
  3065.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 4);
  3066.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 4);
  3067. }
  3068.  
  3069. // Must have blank line at EOF.
  3070.