home *** CD-ROM | disk | FTP | other *** search
/ Doom I/II Collection / DM12.ISO / menus / dmijum / jumble.c < prev    next >
C/C++ Source or Header  |  1994-04-03  |  26KB  |  675 lines

  1. /*
  2.  *    JUMBLE.C
  3.  *
  4.  *    Version 1.0.0
  5.  *
  6.  *    Abstract:
  7.  *     This program creates a file, JUMBLE.WAD, that contains the 27 maps
  8.  *     from DOOM in a random order. The things (characters, items, etc.) in each
  9.  *     map are shuffled and start out facing in a random direction.  Each map
  10.  *     has a song randomly assigned to it.  The Boss levels are special
  11.  *     exceptions: they remain in the same place (map 8), but they get new,
  12.  *     wacky music never before heard in a map. Take note: JUMBLE.WAD is over
  13.  *     3 megs in size. E3M8 is handled specially, and it is twisted!
  14.  *
  15.  *     After creating JUMBLE.WAD, run DOOM with this form:
  16.  *      DOOM -file JUMBLE.WAD { other parameters }
  17.  *
  18.  *    History:
  19.  *     1.0.0    (April 3, 1994)
  20.  *
  21.  *  Author:
  22.  *     Michael McMahon
  23.  *
  24.  ****************************************************************************
  25.  * Jumble Function Directory
  26.  *---------------------------------------------------------------------------
  27.  *Index: Name                     : Description
  28.  *---------------------------------------------------------------------------
  29.  * #1  : WadfileCopyAndJumbleMap : Can be used instead of 'WadfileCopyMap'.
  30.  ****************************************************************************
  31.  *
  32.  *  WADLIB SOFTWARE LICENSE AGREEMENT
  33.  *
  34.  *    1. GRANT OF LICENSE. Michael McMahon and his affiliations (collectively
  35.  *       the "AUTHOR") grant you (either an individual or an entity) the
  36.  *       non-exclusive, royalty-free right to use this library source code,
  37.  *       documentation, and sample code (collectively, the "SOFTWARE") for
  38.  *       any lawful purpose subject to the terms of this license.  By using the
  39.  *       SOFTWARE you are agreeing to be bound to all the terms of this license.
  40.  *
  41.  *    2. COPYRIGHT.  The SOFTWARE is Copyright (c) 1994, Michael McMahon,
  42.  *       PO Box 14807, San Luis Nabisco, CA 93406-4807 USA. All Rights Reserved
  43.  *       Worldwide.  You may not use, modify, or distribute the SOFTWARE except
  44.  *       as otherwise provided herein.
  45.  *
  46.  *    3. DECLARATION OF PUBLIC DOMAIN DISTRIBUTION AND USE. The distribution
  47.  *       and use of the SOFTWARE is hereby designated PUBLIC DOMAIN by the
  48.  *       the AUTHOR.    You may not sell, rent, or lease this SOFTWARE.  The
  49.  *       SOFTWARE may be reproduced verbatim in part or in full by any
  50.  *       reproduction means for any lawful purpose, and may also be subject to
  51.  *       the following agreement.
  52.  *
  53.  *    4. AGREEMENT FOR USE OF SOFTWARE. The AUTHOR grants you a non-exclusive,
  54.  *       royalty-free right to incorporate the SOFTWARE into any production for
  55.  *       any legal purpose as long as you agree
  56.  *        (a) to indemnify, hold harmless, and defend the AUTHOR from and against
  57.  *            any claims or lawsuits, including attorneys' fees, that arise or
  58.  *            result from the use or distribution of your software production; and
  59.  *        (b) no matter how much the SOFTWARE is modified, the AUTHOR owns the
  60.  *            copyright and this original, unmodified copyright notice remains
  61.  *            intact in the source code; and,
  62.  *        (c) the AUTHOR is not held responsible for fixing bugs or making
  63.  *            enhancements or changes to the SOFTWARE for any reason; and,
  64.  *        (d) the SOFTWARE is not redistributed if it is modified in any way; and,
  65.  *      (e) otherwise comply with the terms of this agreement; and,
  66.  *        (f) the AUTHOR is forgiven for making so many demands.
  67.  *
  68.  *     THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. THE
  69.  *     AUTHOR FURTHER DISCLAIMS ALL IMPLIED WARRANTIES, INCLUDING WITHOUT
  70.  *     LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR OF FITNESS
  71.  *     FOR A PARTICULAR PURPOSE.    THE ENTIRE RISK ARISING OUT OF THE USE
  72.  *     OR PERFORMANCE OF THE SOFTWARE REMAINS WITH YOU.
  73.  *
  74.  *     The author can be reached at:
  75.  *      Michael McMahon
  76.  *      P.O. Box 14807
  77.  *      San Luis Nabisco, CA 93406-4807 USA
  78.  *      Internet: mmcmahon@oboe.calpoly.edu
  79.  *      [Bug reports, suggestions, success stories, etc. are welcome; tech
  80.  *       support, and other unnecessary two-way mail, is not]
  81.  */
  82.  
  83. #include <assert.h>
  84. #include <stdio.h>
  85. #include <stdlib.h>
  86. #include <malloc.h>
  87. #include <mem.h>
  88. #include <time.h>
  89. #include "general.h"
  90. #include "wadfile.h"
  91. #include "dm_mapdf.h"
  92.  
  93. /* Program-specific definitions */
  94. #define PROG_FILENAME "JUMBLE"
  95. #define PROG_AUTHOR   "Michael McMahon"
  96.  
  97. /* Values to be returned to the operating system */
  98. #define EXIT_ERROR -1
  99. #define EXIT_OK    0
  100.  
  101. /* System bounds */
  102. #define MAX_ENTRIES 500
  103. #define FILE_NAME_SIZE 200
  104.  
  105. /* Target filename */
  106. #define JUMBLE_NAME "JUMBLE.WAD"
  107.  
  108. /* Jumble structure */
  109. typedef struct {
  110.     int episode;
  111.     int map;
  112.     int touched;
  113.     char musicName[SIZEOF_WAD_DIR_ENTRY];
  114. } JumbledMapRec;
  115.  
  116. /* Funny BOSS level music */
  117. char * bossEpisodeMusic[DOOM_LASTEPISODE]={"D_VICTOR","D_INTRO\0","D_BUNNY\0"};
  118.  
  119. /* Maximum allowable THINGS per map */
  120. #define MAX_THINGS 1000
  121.  
  122. /* Record used to shuffle THINGS */
  123. struct {
  124.     int newLocation;
  125.     int touched;
  126. } jumbledThings[MAX_THINGS];
  127.  
  128. /* Symbol used to determine what maps still need to be defined */
  129. #define JUMBLEREC_UNTOUCHED 0
  130. #define JUMBLEREC_TOUCHED    1
  131.  
  132. /* Thing types */
  133. #define TYPE_PLAYER1START        1
  134. #define TYPE_PLAYER2START        2
  135. #define TYPE_PLAYER3START        3
  136. #define TYPE_PLAYER4START        4
  137. #define TYPE_BLUEKEY            5
  138. #define TYPE_YELLOWKEY            6
  139. #define TYPE_SPIDERDEMON        7
  140. #define TYPE_DEATHMATCHPOS        11
  141. #define TYPE_REDKEY             13
  142. #define TYPE_TELEPORTER         14
  143. #define TYPE_CYBERLORD            16
  144. #define TYPE_CELL_CASE            17
  145. #define TYPE_REDSKULL            38
  146. #define TYPE_YELLOWSKULL        39
  147. #define TYPE_BLUESKULL            40
  148. #define TYPE_INVULNERABILITY    2022
  149. #define TYPE_CELL_CHARGE        2047
  150. #define TYPE_BARON                3003
  151. #define TYPE_HUMAN                3004
  152. #define TYPE_CACODEMON            3005
  153.  
  154. /* Constants used in randomizing angle THINGS initially face */
  155. #define NUM_FACES       8
  156. #define TOTAL_DEGREES    360
  157.  
  158. /*------------------------- Internal routines ---------------------------*/
  159.  
  160. /**[ Internal 1 of 2 ]****************************************************
  161.  *                                                                       *
  162.  *      wadMalloc                                                          *
  163.  *                                                                         *
  164.  * Desc:                                                                 *
  165.  *       This is the memory allocation routine for this example program.     *
  166.  *       The memory management routines are stored outside WADFILE.C so     *
  167.  *       it would be compatible with any memory manager.    This example     *
  168.  *       uses ANSI C's malloc.                                             *
  169.  *                                                                         *
  170.  * Def:                                                                  *
  171.  *       static void * wadMalloc(unsigned long size);                      *
  172.  *                                                                       *
  173.  * Parm:                                                                 *
  174.  *       size    Number of bytes to allocate.                              *
  175.  *                                                                         *
  176.  * Retn:                                                                 *
  177.  *       Pointer to allocated memory, or NULL if not enough memory.         *
  178.  *                                                                         *
  179.  * Notes:                                                                *
  180.  *     Use a pointer to this routine as the first parameter in the       *
  181.  *     'WadfileInitialize' call.                                         *
  182.  *                                                                         *
  183.  *************************************************************************/
  184.  
  185. static void * wadMalloc (unsigned long size)
  186. {
  187.   /* Note: If size is > 64k, some implementations of malloc might not work */
  188.     return malloc(size);
  189. }
  190.  
  191. /**[ Internal 2 of 2 ]****************************************************
  192.  *                                                                       *
  193.  *      wadFree                                                             *
  194.  *                                                                       *
  195.  * Desc:                                                                 *
  196.  *       This is the memory deallocation routine for this example program. *
  197.  *       The memory management routines are stored outside WADFILE.C so     *
  198.  *       it would be compatible with any memory manager.    This example     *
  199.  *       uses ANSI C's free.                                               *
  200.  *                                                                       *
  201.  * Def:                                                                  *
  202.  *       static void wadFree(void * ptr);                                  *
  203.  *                                                                       *
  204.  * Parm:                                                                 *
  205.  *       ptr       Valid memory pointer that was allocated with wadMalloc.     *
  206.  *                                                                       *
  207.  * Retn:                                                                 *
  208.  *       None                                                              *
  209.  *                                                                         *
  210.  * Notes:                                                                *
  211.  *       Use a pointer to this routine as the second parameter in the      *
  212.  *     'WadfileInitialize' call.                                         *
  213.  *                                                                       *
  214.  *************************************************************************/
  215.  
  216. static void wadFree(void * ptr)
  217. {
  218.     /* Release memory */
  219.     free(ptr);
  220. }
  221.  
  222. /*------------------------- Utility routines ------------------------------*/
  223.  
  224. /**[ #1 ]*****************************************************************
  225.  *                                                                         *
  226.  *      WadfileCopyAndJumbleMap                                             *
  227.  *                                                                         *
  228.  * Desc:                                                                 *
  229.  *       This copies an arbitrary map from an open Wadfile to a Wadfile     *
  230.  *       that is being created, jumbling the THINGS section. Do not use     *
  231.  *       'WadfileLumpOpen' or 'WadfileLumpClose' to initialize and release *
  232.  *       the lump data; this routine is self-contained and opens, copies,  *
  233.  *       and closes the lump data in one fell swoop.                         *
  234.  *                                                                         *
  235.  * Def:                                                                  *
  236.  *       int WadfileCopyAndJumbleMap(Wadfile * dest, int destEpisode,      *
  237.  *           int destMap, Wadfile * src,    int srcEpisode,  int srcMap)     *
  238.  *                                                                       *
  239.  * Parm:                                                                 *
  240.  *       dest         A Wadfile that is being created.                     *
  241.  *       destEpisode    The new episode number for the map data.             *
  242.  *       destMap        The new map number for the map data.                 *
  243.  *       src            An existing Wadfile.                                 *
  244.  *       srcEpisode    The old episode number for the map data.             *
  245.  *       srcMap        The old map number for the map data.                 *
  246.  *                                                                       *
  247.  * Retn:                                                                 *
  248.  *       TRUE if map is copied succesfully; FALSE otherwise.                 *
  249.  *                                                                         *
  250.  * Notes:                                                                 *
  251.  *       On a 16-bit platform, this successfully copies lumps larger         *
  252.  *       than 64k.                                                         *
  253.  *                                                                         *
  254.  *       E3M8 (Spiderdemon) is handled specially. The values are always     *
  255.  *       the same.                                                         *
  256.  *                                                                       *
  257.  *************************************************************************/
  258.  
  259. int WadfileCopyAndJumbleMap(Wadfile * dest, int destEpisode, int destMap,
  260.                    Wadfile * src,  int srcEpisode,  int srcMap)
  261. {
  262.     int i,j,k;                      /* Loop control and scratchpad variables */
  263.     unsigned long location;       /* Starting location of lump               */
  264.     int numItems;                  /* The count of the items in a lump       */
  265.     char * ptr;                   /* Used to access in-memory 'dirCache'   */
  266.     char targetName[SIZEOF_WAD_DIR_NAME];
  267.     ThingRec * allThings;          /* THINGS array used in jumbling           */
  268.     ThingRec thing;
  269.     unsigned long numThingsAdded;
  270.  
  271.  
  272.     numThingsAdded = 0;
  273.  
  274.     /* Seek to map location, if possible */
  275.     if (!WadfileSeekMap(src, srcEpisode, srcMap)) return FALSE;
  276.  
  277.     /* Copy the source map to destination map */
  278.     if (!WadfileLumpOpen(src)) return FALSE;
  279.     sprintf(targetName, "E%dM%d\0\0\0\0", destEpisode, destMap);
  280.     if (!WadfileAddLump(dest, src->lumpSize, targetName, src->lumpData))
  281.      return FALSE;
  282.     if (!WadfileLumpClose(src)) return FALSE;
  283.  
  284.     /* Now that this is copied, go to next entry */
  285.     WadfileGetNextDirInfo(src);
  286.  
  287.     /* Copy and jumble the THINGS section */
  288.     location = ftell(dest->wf);
  289.  
  290.     /* Position the file to the beginning of the THINGS section */
  291.     if (!WadfileLumpOpen(src)) return FALSE;
  292.     allThings =  (ThingRec *) src->lumpData;
  293.  
  294.     /* How many THINGS? */
  295.     numItems = src->entrySize/sizeof(ThingRec);
  296.  
  297.     /* E3M8 is handled elsewhere */
  298.     if (!((destEpisode==3)&&(destMap==8)))
  299.     {
  300.     /* Clear jumbled THINGS record */
  301.     for (i=0; i<numItems; i++)
  302.     {
  303.      /* Exclude certain types from jumbling */
  304.      if ((allThings[i].type == TYPE_PLAYER1START) ||
  305.          (allThings[i].type == TYPE_PLAYER2START) ||
  306.          (allThings[i].type == TYPE_PLAYER3START) ||
  307.          (allThings[i].type == TYPE_PLAYER4START) ||
  308.          (allThings[i].type == TYPE_DEATHMATCHPOS) ||
  309.          (allThings[i].type == TYPE_BLUEKEY) ||
  310.          (allThings[i].type == TYPE_YELLOWKEY) ||
  311.          (allThings[i].type == TYPE_REDKEY) ||
  312.          (allThings[i].type == TYPE_BLUESKULL) ||
  313.          (allThings[i].type == TYPE_YELLOWSKULL) ||
  314.          (allThings[i].type == TYPE_REDSKULL) ||
  315.          (allThings[i].type == TYPE_TELEPORTER))
  316.       jumbledThings[i].touched = JUMBLEREC_TOUCHED;
  317.      else
  318.      jumbledThings[i].touched = JUMBLEREC_UNTOUCHED;
  319.     }
  320.  
  321.     /* Jumble the THINGS */
  322.     for (i=0; i<numItems; i++)
  323.     {
  324.  
  325.      if (!((allThings[i].type == TYPE_PLAYER1START) ||
  326.          (allThings[i].type == TYPE_PLAYER2START) ||
  327.          (allThings[i].type == TYPE_PLAYER3START) ||
  328.          (allThings[i].type == TYPE_PLAYER4START) ||
  329.          (allThings[i].type == TYPE_DEATHMATCHPOS) ||
  330.          (allThings[i].type == TYPE_BLUEKEY) ||
  331.          (allThings[i].type == TYPE_YELLOWKEY) ||
  332.          (allThings[i].type == TYPE_REDKEY) ||
  333.          (allThings[i].type == TYPE_BLUESKULL) ||
  334.          (allThings[i].type == TYPE_YELLOWSKULL) ||
  335.          (allThings[i].type == TYPE_REDSKULL) ||
  336.          (allThings[i].type == TYPE_TELEPORTER)))
  337.      {
  338.        /* Find an open spot randomly */
  339.        do{
  340.        j = rand()%numItems;
  341.        } while (jumbledThings[j].touched == JUMBLEREC_TOUCHED);
  342.  
  343.        /* Mark as touched, and store new location */
  344.        jumbledThings[j].touched = JUMBLEREC_TOUCHED;
  345.        jumbledThings[j].newLocation = i;
  346.      }
  347.      else
  348.       /* Don't move it */
  349.       jumbledThings[i].newLocation = i;
  350.     }
  351.  
  352.     /* Write the THINGS, one by one, to disk */
  353.     for (i=0; i<numItems; i++)
  354.     {
  355.       /* Fill the 'thing' structure */
  356.       thing.x       =  allThings[jumbledThings[i].newLocation].x;
  357.       thing.y       =  allThings[jumbledThings[i].newLocation].y;
  358.       thing.angle  =  (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  359.       thing.type   =  allThings[i].type;
  360.       thing.flags  =  allThings[i].flags;
  361.  
  362.       /* Write it to disk */
  363.       fwrite(&thing, sizeof(thing), 1, dest->wf);
  364.       numThingsAdded++;
  365.     }
  366.     }
  367.    else
  368.     {
  369.     /* E3M8 handler */
  370.  
  371.     /* 'j' counts the number of cacodemons processed */
  372.     j=0;
  373.  
  374.     /* Write the THINGS, one by one, to disk */
  375.     for (i=0; i<numItems; i++)
  376.     {
  377.       /* Fill the 'thing' structure */
  378.       thing.x      =  allThings[i].x;
  379.       thing.y      =  allThings[i].y;
  380.       thing.angle  =  allThings[i].angle;
  381.       switch (allThings[i].type)
  382.       {
  383.        case TYPE_CACODEMON:  j++;
  384.                               if (j==1)
  385.                                 thing.type = TYPE_CYBERLORD;
  386.                               else
  387.                                 thing.type = TYPE_SPIDERDEMON;
  388.                               break;
  389.  
  390.        case TYPE_BARON:
  391.                               thing.type = TYPE_INVULNERABILITY;
  392.                               break;
  393.  
  394.        case TYPE_CELL_CHARGE:
  395.                               thing.type = TYPE_CELL_CASE;
  396.                               break;
  397.  
  398.        case TYPE_PLAYER2START:
  399.                               thing.type = TYPE_PLAYER1START;
  400.                               break;
  401.  
  402.        case TYPE_PLAYER1START:
  403.        case TYPE_PLAYER3START:
  404.                               thing.type = TYPE_BARON;
  405.                               break;
  406.  
  407.  
  408.        case TYPE_PLAYER4START:
  409.                               thing.type = TYPE_HUMAN;
  410.                               break;
  411.  
  412.        default:               thing.type = allThings[i].type;
  413.                               break;
  414.       }
  415.       thing.flags  =  THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4;
  416.  
  417.       /* Write it to disk */
  418.       fwrite(&thing, sizeof(thing), 1, dest->wf);
  419.       numThingsAdded++;
  420.     }
  421.  
  422.     /* Add the new player starting locations */
  423.     thing.x     = -1536;
  424.     thing.y     = -943;
  425.     thing.angle = (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  426.     thing.type    = TYPE_PLAYER2START;
  427.     thing.flags = THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4;
  428.     fwrite(&thing, sizeof(thing), 1, dest->wf);
  429.     numThingsAdded++;
  430.     thing.x     = -1651;
  431.     thing.y     = -968;
  432.     thing.angle = (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  433.     thing.type    = TYPE_PLAYER3START;
  434.     thing.flags = THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4;
  435.     fwrite(&thing, sizeof(thing), 1, dest->wf);
  436.     numThingsAdded++;
  437.     thing.x     = -1481;
  438.     thing.y     = -1068;
  439.     thing.angle = (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  440.     thing.type    = TYPE_PLAYER4START;
  441.     thing.flags = THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4;
  442.     fwrite(&thing, sizeof(thing), 1, dest->wf);
  443.     numThingsAdded++;
  444.  
  445.  
  446.     /* How BOSS Levels (Episodes 2 and 3) work.
  447.  
  448.        The rule is this: when a boss dies, if there are no other bosses
  449.        like it alive on the level, the game ends. Since in this map there
  450.        are two types of bosses, two extra bosses have to be added outside
  451.        the map (deaf) so the game doesn't end early. In fact, this level
  452.        doesn't end even when all visible opponents are dead. */
  453.  
  454.     /* Add a BOSS, so game won't end prematurely */
  455.     thing.x     = -171;
  456.     thing.y     = -863;
  457.     thing.angle = (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  458.     thing.type    = TYPE_CYBERLORD;
  459.     thing.flags = THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4 | THING_DEAF;
  460.     fwrite(&thing, sizeof(thing), 1, dest->wf);
  461.     numThingsAdded++;
  462.  
  463.     /* Add another BOSS, so game won't end prematurely */
  464.     thing.x     = -1296;
  465.     thing.y     = 507;
  466.     thing.angle = (rand()%NUM_FACES)*(TOTAL_DEGREES/NUM_FACES);
  467.     thing.type    = TYPE_SPIDERDEMON;
  468.     thing.flags = THING_LEVEL12 | THING_LEVEL3 | THING_LEVEL4 | THING_DEAF;
  469.     fwrite(&thing, sizeof(thing), 1, dest->wf);
  470.     numThingsAdded++;
  471.  
  472.     }
  473.  
  474.     /* Bump up 'entryIndex' */
  475.     if (dest->entryIndex == INVALID_ENTRY)
  476.       dest->entryIndex = 0;
  477.     else
  478.       dest->entryIndex++;
  479.     if (dest->entryIndex >= dest->dirNumEntries) return FALSE;
  480.  
  481.     /* Copy data to 'dirCache' */
  482.     ptr = &dest->dirCache[dest->entryIndex*SIZEOF_WAD_DIR_ENTRY];
  483.     memcpy(ptr, &location, SIZEOF_WAD_DIR_LOCATION);
  484.     ptr += SIZEOF_WAD_DIR_LOCATION;
  485.     numThingsAdded *= sizeof(ThingRec);
  486.     memcpy(ptr, &numThingsAdded, SIZEOF_WAD_DIR_SIZE);
  487.     ptr += SIZEOF_WAD_DIR_SIZE;
  488.     memcpy(ptr, src->entryName, SIZEOF_WAD_DIR_NAME);
  489.  
  490.     /* Release THING memory */
  491.     WadfileLumpClose(src);
  492.  
  493.  
  494.     WadfileGetNextDirInfo(src);
  495.  
  496.     /* Write out all other sections of the map */
  497.     for (i=0; i<NUM_ENTRIES_PER_MAP-2; i++)
  498.     {
  499.         /* Copy lump from source to destination */
  500.         if (!WadfileLumpCopy(dest, src->entryName, src))
  501.          return FALSE;
  502.  
  503.         /* Go to next entry in the directory */
  504.         WadfileGetNextDirInfo(src);
  505.     }
  506.  
  507.     return TRUE;
  508. }
  509.  
  510.  
  511. /*---------------------------- Main routine ------------------------------*/
  512.  
  513. /*************************************************************************
  514.  *                                                                       *
  515.  *      main                                                                 *
  516.  *                                                                       *
  517.  * Desc:                                                                 *
  518.  *       This creates a PWAD file for every map in DOOM's Wadfile.         *
  519.  *                                                                       *
  520.  * Def:                                                                  *
  521.  *       int main(int argc, char * argv[]);                                 *
  522.  *                                                                         *
  523.  * Parm:                                                                 *
  524.  *       argc     Number of parameters                                     *
  525.  *       argv     List of parameters                                         *
  526.  *                                                                       *
  527.  * Retn:                                                                 *
  528.  *       TRUE if all maps were copied successfully, FALSE otherwise.         *
  529.  *                                                                         *
  530.  * Notes:                                                                *
  531.  *       Suggestion: You can rename this routine and call it from another  *
  532.  *       module.                                                             *
  533.  *                                                                       *
  534.  *************************************************************************/
  535.  
  536. int main(int argc, char * argv[])
  537. {
  538.     int episode, map;    /* Loop control variables    */
  539.     int i;
  540.     JumbledMapRec jumbleMap[DOOM_LASTEPISODE*DOOM_LASTMAP];
  541.     char musicName[SIZEOF_WAD_DIR_NAME];
  542.     unsigned long seed; /* Pseudo-random number generator seed */
  543.     Wadfile wad;        /* DOOM's IWAD file pointer */
  544.     Wadfile jumbleWad;    /* JUMBLE.WAD Wadfile        */
  545.  
  546.     /* Print title */
  547.     fprintf(stdout, "DOOM WAD Utility: %s\n",  PROG_FILENAME);
  548.     fprintf(stdout, "This program has no affiliation with ID Software.\n");
  549.     fprintf(stdout, "Use at your own discretion.\n");
  550.     fprintf(stdout, "Author: %s    Date: %s\n\n\n", PROG_AUTHOR, __DATE__);
  551.  
  552.     /* Check command line */
  553.     if (argc < 2)
  554.     {
  555.         fprintf(stderr, "Format:  %s filename.wad [random seed]", PROG_FILENAME);
  556.         return EXIT_ERROR;
  557.     }
  558.  
  559.     /* A one-time Wadfile initialization to set up memory management */
  560.     WadfileInitialize(wadMalloc, wadFree);
  561.  
  562.     /* Open WAD file, aborting if error or if it is a PWAD file */
  563.     if (!WadfileOpen(&wad, argv[1], WANTIWAD))
  564.     {
  565.      printf("Sorry, %s is not an IWAD file.\nAdios!\n", argv[1]);
  566.      return EXIT_ERROR;
  567.     }
  568.  
  569.     /* Tip: Echo the command line parameter(s) to the user */
  570.     printf("Processing WAD file: %s\n", argv[1]);
  571.  
  572.     /* Make sure this is a registered version of DOOM by looking for E3M1 */
  573.     /* Only check if file is an IWAD (that is, it came from id Software.) */
  574.     if ((wad.flags & FLAG_WADFILE_IWAD) && (!WadfileSeekMap(&wad, 3, 1)))
  575.      {
  576.         printf("Cannot work with SHAREWARE DOOM. Buy DOOM and try again.\n");
  577.         return EXIT_ERROR;
  578.      }
  579.  
  580.     /* Create a new jumble PWAD */
  581.     unlink(JUMBLE_NAME);
  582.     if (!WadfileCreate(&jumbleWad, JUMBLE_NAME, TYPE_PWAD, MAX_ENTRIES))
  583.     {
  584.      fprintf(stderr, "Error creating %s!\n", JUMBLE_NAME);
  585.      return FALSE;
  586.     }
  587.  
  588.     /* Randomize by either the parameter on command line or by the
  589.        system clock */
  590.     if (argc > 2)
  591.      seed = atol(argv[2]);
  592.     else
  593.      seed = (unsigned long)time(0);
  594.     srand(seed);
  595.     printf("Using random seed: %lu.\n", seed);
  596.  
  597.     /* Initialize jumbled map */
  598.     for (episode=0; episode<DOOM_LASTEPISODE; episode++)
  599.      for (map=0; map<DOOM_LASTMAP; map++)
  600.      {
  601.        jumbleMap[episode*DOOM_LASTMAP+map].touched = JUMBLEREC_UNTOUCHED;
  602.  
  603.        /* Create the music name for this level--this is completely random;
  604.           some songs are used many times, some not at all. */
  605.        sprintf(jumbleMap[episode*DOOM_LASTMAP+map].musicName, "D_E%dM%d\0",
  606.                1+(rand() % DOOM_LASTEPISODE), 1+(rand() % DOOM_LASTMAP));
  607.      }
  608.  
  609.     /* The BOSS levels must stay in the same place, or else they won't end. */
  610.     for (episode=0; episode<DOOM_LASTEPISODE; episode++)
  611.     {
  612.        jumbleMap[episode*DOOM_LASTMAP+DOOM_BOSSLEVEL-1].episode = episode+1;
  613.        jumbleMap[episode*DOOM_LASTMAP+DOOM_BOSSLEVEL-1].map     = DOOM_BOSSLEVEL;
  614.         memcpy(jumbleMap[episode*DOOM_LASTMAP+DOOM_BOSSLEVEL-1].musicName,
  615.                bossEpisodeMusic[episode], SIZEOF_WAD_DIR_NAME);
  616.        jumbleMap[episode*DOOM_LASTMAP+DOOM_BOSSLEVEL-1].touched = JUMBLEREC_TOUCHED;
  617.     }
  618.  
  619.     /* Create the jumble map */
  620.     for (episode=0; episode<DOOM_LASTEPISODE; episode++)
  621.      for (map=0; map<DOOM_LASTMAP; map++)
  622.       {
  623.        if (map != (DOOM_BOSSLEVEL-1))
  624.        {
  625.        do{
  626.        i = rand()%(DOOM_LASTEPISODE*DOOM_LASTMAP);
  627.        } while (jumbleMap[i].touched == JUMBLEREC_TOUCHED);
  628.  
  629.        jumbleMap[i].touched = JUMBLEREC_TOUCHED;
  630.        jumbleMap[episode*DOOM_LASTMAP+map].episode = (i/DOOM_LASTMAP)+1;
  631.        jumbleMap[episode*DOOM_LASTMAP+map].map       = (i%DOOM_LASTMAP)+1;
  632.        }
  633.       }
  634.  
  635.     /* Tip: Give the user something to read */
  636.     printf("Creating %s\n", JUMBLE_NAME);
  637.  
  638.     /* Do the jumbling one map at a time */
  639.      for (episode=0; episode<DOOM_LASTEPISODE; episode++)
  640.      for (map=0; map<DOOM_LASTMAP; map++)
  641.      {
  642.         /* Tip: Give the user something to read */
  643.         printf("Jumbling E%dM%d using a map from episode %d.\n",episode+1, map+1,
  644.            jumbleMap[episode*DOOM_LASTMAP+map].episode);
  645.  
  646.         /* Create the music name for this level */
  647.         sprintf(musicName, "D_E%dM%d\0", episode+1, map+1);
  648.  
  649.         /* Extract a map, jumble it, and write it to JUMBLE.WAD */
  650.         if ((!WadfileCopyAndJumbleMap(&jumbleWad, episode+1, map+1, &wad,
  651.            jumbleMap[episode*DOOM_LASTMAP+map].episode,
  652.            jumbleMap[episode*DOOM_LASTMAP+map].map)) ||
  653.          (!WadfileCopyEntry(&jumbleWad, musicName,
  654.                             &wad, jumbleMap[episode*DOOM_LASTMAP+map].musicName)))
  655.         {
  656.             fprintf(stderr, "Error creating %s.\n", JUMBLE_NAME);
  657.             return EXIT_ERROR;
  658.         }
  659.       }
  660.  
  661.     /* This reassures the user the process is ending successfully */
  662.     printf("Done!\n\n");
  663.  
  664.     /* Close up shop */
  665.     WadfileClose(&jumbleWad);
  666.     WadfileClose(&wad);
  667.     printf("Now, run DOOM by typing:\n");
  668.     printf("  DOOM -file JUMBLE.WAD { other normal paramters }\n\n");
  669.     printf("See JUMBLE.DOC for more specific help.\n");
  670.     return EXIT_OK;
  671. }
  672.  
  673.  
  674.  
  675.