diff -c pmars1/clparse.c pmars2/clparse.c
*** pmars1/clparse.c	Tue Feb 20 13:15:32 1996
--- pmars2/clparse.c	Wed Oct 20 22:35:58 1999
***************
*** 65,71 ****
         *optKotH, *optLength, *opt88, *optDistance, *optFixedSeries, *optFixedPosition,
         *optSort, *optView, *optScoreFormula, *optDIAOutput, *noWarriorFile,
         *fFExclusive, *coreSizeTooSmall, *dLessThanl, *FLessThand, *FTooBig,
!        *outOfMemory, *badScoreFormula, *optPSpaceSize, *pSpaceTooBig;
  
  #if defined(XWINGRAPHX)
  extern char *badArgumentForXSwitch, *optXOpt[];
--- 65,72 ----
         *optKotH, *optLength, *opt88, *optDistance, *optFixedSeries, *optFixedPosition,
         *optSort, *optView, *optScoreFormula, *optDIAOutput, *noWarriorFile,
         *fFExclusive, *coreSizeTooSmall, *dLessThanl, *FLessThand, *FTooBig,
!        *outOfMemory, *badScoreFormula, *optPSpaceSize, *pSpaceTooBig,
!        *optPermutate, *permutateMultiWarrior;
  
  #if defined(XWINGRAPHX)
  extern char *badArgumentForXSwitch, *optXOpt[];
***************
*** 454,466 ****
    * command line parameters and options                              *
    ********************************************************************/
  
! #define OPTNUM 20                /* don't forget to increase when adding new
                                   * options */
    static clp_opt_t options[OPTNUM];
    int     optI = 0;                /* used by record() macro */
  
    record('r', clp_int, &rounds, 0, MAXROUND,
           DEFAULTROUNDS, optRounds);
  #ifndef SERVER
    record('e', clp_bool, &SWITCH_e, 0, 1,
           0, optEnterDebugger);
--- 455,472 ----
    * command line parameters and options                              *
    ********************************************************************/
  
! #define OPTNUM 21                /* don't forget to increase when adding new
                                   * options */
    static clp_opt_t options[OPTNUM];
    int     optI = 0;                /* used by record() macro */
  
+ #ifdef PERMUTATE
+   record('r', clp_int, &rounds, 0, MAXROUND,
+          -1, optRounds);
+ #else
    record('r', clp_int, &rounds, 0, MAXROUND,
           DEFAULTROUNDS, optRounds);
+ #endif
  #ifndef SERVER
    record('e', clp_bool, &SWITCH_e, 0, 1,
           0, optEnterDebugger);
***************
*** 495,500 ****
--- 501,510 ----
    record('S', clp_addr, &pSpaceSize, 1,
           MAXCORESIZE, 0, optPSpaceSize);
  #endif
+ #ifdef PERMUTATE
+   record('P', clp_bool, &SWITCH_P, 0, 1,
+ 	 0, optPermutate);
+ #endif
    record('=', clp_str, &SWITCH_eq, 0, 0, 0, optScoreFormula);
    record('Q', clp_int, &SWITCH_Q, -1, INT_MAX, -1, NULL);
  #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX)  || defined(LINUXGRAPHX) \
***************
*** 547,557 ****
          errout(fFExclusive);
          result = CLP_NOGOOD;
        }
-       if (coreSize < (warriors * separation / 2)) {
-         print_usage(options);
-         errout(coreSizeTooSmall);
-         result = CLP_NOGOOD;
-       }
        if (separation == 0)
          separation = instrLim;
        else if (separation < instrLim) {
--- 557,562 ----
***************
*** 559,564 ****
--- 564,574 ----
          errout(dLessThanl);
          result = CLP_NOGOOD;
        }
+       if (coreSize < (warriors * separation)) {
+         print_usage(options);
+         errout(coreSizeTooSmall);
+         result = CLP_NOGOOD;
+       }
        if ((SWITCH_F) && (separation > SWITCH_F)) {
          print_usage(options);
          errout(FLessThand);
***************
*** 585,595 ****
            if (!(coreSize % i)) {
              pSpaceSize = coreSize / i;
              break;
-           } else if (pSpaceSize > coreSize) {
-             print_usage(options);
-             errout(pSpaceTooBig);
-             result = CLP_NOGOOD;
            }
  #endif
        /* further checks of the values */
  
--- 595,617 ----
            if (!(coreSize % i)) {
              pSpaceSize = coreSize / i;
              break;
            }
+       if (pSpaceSize > coreSize) {
+ 	print_usage(options);
+ 	errout(pSpaceTooBig);
+ 	result = CLP_NOGOOD;
+       }
+ #endif
+ #ifdef PERMUTATE
+       if (SWITCH_P) {
+ 	if (warriors != 2) {
+ 	  print_usage(options);
+ 	  errout(permutateMultiWarrior);
+ 	  result = CLP_NOGOOD;
+ 	} else if (rounds < 0) /* all possible combinations */
+ 	    rounds = 2*coreSize-4*separation+2;
+       } else if (rounds < 0 )
+ 	rounds = DEFAULTROUNDS;
  #endif
        /* further checks of the values */
  
***************
*** 604,606 ****
--- 626,631 ----
    }
    return result;
  }
+ 
+ 
+ 
diff -c pmars1/global.c pmars2/global.c
*** pmars1/global.c	Tue Feb 20 13:15:38 1996
--- pmars2/global.c	Wed Oct 20 22:35:59 1999
***************
*** 50,55 ****
--- 50,58 ----
  #ifdef VMS
  int     SWITCH_D;
  #endif
+ #ifdef PERMUTATE
+ int     SWITCH_P;
+ #endif
  
  #if defined(DOSTXTGRAPHX) || defined(DOSGRXGRAPHX) || defined(LINUXGRAPHX) \
      || defined(XWINGRAPHX)
diff -c pmars1/global.h pmars2/global.h
*** pmars1/global.h	Tue Feb 20 13:15:38 1996
--- pmars2/global.h	Wed Oct 20 22:35:59 1999
***************
*** 311,316 ****
--- 311,319 ----
  #ifdef VMS
  extern int SWITCH_D;
  #endif
+ #ifdef PERMUTATE
+ extern int SWITCH_P;
+ #endif
  
  extern int inCdb;
  extern int debugState;
diff -c pmars1/makefile pmars2/makefile
*** pmars1/makefile	Thu Oct 26 16:07:30 1995
--- pmars2/makefile	Wed Oct 20 22:35:59 1999
***************
*** 14,21 ****
  # (4)   -DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
  # (5)   -DSMALLMEM                          16-bit addresses, less memory
  # (6)   -DXWINGRAPHX    1                   X-Windows graphics (UNIX)
  
! CFLAGS = -O -DEXT94
  LFLAGS = -x
  LIB = -lcurses -ltermlib		# enable this one for curses display
  # LIB = -lvgagl -lvga			# enable this one for Linux/SVGA
--- 14,22 ----
  # (4)   -DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
  # (5)   -DSMALLMEM                          16-bit addresses, less memory
  # (6)   -DXWINGRAPHX    1                   X-Windows graphics (UNIX)
+ # (7)   -DPERMUTATE                         enables -P switch
  
! CFLAGS = -O -DEXT94 -DPERMUTATE
  LFLAGS = -x
  LIB = -lcurses -ltermlib		# enable this one for curses display
  # LIB = -lvgagl -lvga			# enable this one for Linux/SVGA
diff -c pmars1/makefile.djg pmars2/makefile.djg
*** pmars1/makefile.djg	Sat Apr  8 13:03:28 1995
--- pmars2/makefile.djg	Wed Oct 20 22:35:59 1999
***************
*** 9,15 ****
  #                                           graphics
  # (3)   -DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
  # (4)   -DSMALLMEM                          16-bit addresses, less memory
! CFLAGS = -O2 -m486 -DGRAPHX -DEXT94
  # only tested with PDCurses (-lcurses)
  LIB = -lgrx -lpc
   
--- 9,16 ----
  #                                           graphics
  # (3)   -DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
  # (4)   -DSMALLMEM                          16-bit addresses, less memory
! # (5)   -DPERMUTATE                         enables -P switch
! CFLAGS = -O2 -m486 -DGRAPHX -DEXT94 -DPERMUTATE
  # only tested with PDCurses (-lcurses)
  LIB = -lgrx -lpc
   
Only in pmars2: makefile.orig
diff -c pmars1/makefile.wat pmars2/makefile.wat
*** pmars1/makefile.wat	Thu Jan 11 17:17:48 1996
--- pmars2/makefile.wat	Wed Oct 20 22:35:59 1999
***************
*** 5,19 ****
  # Configuration options:
  #
  # No.   Name            Incompatible with   Description
! # (1)   -DSERVER        2                   disables cdb debugger (koth server 
  #                                           version)
! # (2)   -DGRAPHX        1                   enables platform specific core 
  #                                           graphics
! # (3)   -DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
! # (4)   -DSMALLMEM                          16-bit addresses, less memory
  
  CC = wcc386
! CFLAGS  = /mf /wx /s /oneatx /DWATCOM /DEXT94 /DGRAPHX /DDOSTXTGRAPHX
  
  OBJS = pmars.obj asm.obj eval.obj disasm.obj cdb.obj pos.obj &
         clparse.obj global.obj token.obj str_eng.obj sim.obj
--- 5,20 ----
  # Configuration options:
  #
  # No.   Name            Incompatible with   Description
! # (1)   /DSERVER        2                   disables cdb debugger (koth server 
  #                                           version)
! # (2)   /DGRAPHX        1                   enables platform specific core 
  #                                           graphics
! # (3)   /DEXT94                             ICWS'94 + SEQ,SNE,NOP,*,{,}
! # (4)   /DSMALLMEM                          16-bit addresses, less memory
! # (5)   /DPERMUTATE                         enables -P switch
  
  CC = wcc386
! CFLAGS  = /mf /wx /s /oneatx /DWATCOM /DEXT94 /DGRAPHX /DDOSTXTGRAPHX /DPERMUTATE
  
  OBJS = pmars.obj asm.obj eval.obj disasm.obj cdb.obj pos.obj &
         clparse.obj global.obj token.obj str_eng.obj sim.obj
diff -c pmars1/pmars.6 pmars2/pmars.6
*** pmars1/pmars.6	Tue Feb 20 13:40:38 1996
--- pmars2/pmars.6	Wed Oct 20 22:35:59 1999
***************
*** 191,196 ****
--- 191,207 ----
  exclusive. If neither option is specified, the pseudo random number
  generator is initialized with the system time.
  .TP
+ .BI \-P
+ This option makes
+ .I pMARS
+ use an alternative algorithm for positioning warriors. This algorithm uses
+ all possible combinations of starting order and position in a random
+ sequence, and will not use the same combination twice unless all the
+ combinations have already been used. If the \-r option is not given, the
+ number of rounds fought will be the number of all possible combinations.
+ Trying to use this option with more (or less) than two warriors causes an
+ error.
+ .TP
  .BI \-e
  If this option is specified, the
  .I cdb
diff -c pmars1/sim.c pmars2/sim.c
*** pmars1/sim.c	Tue Feb 20 13:15:48 1996
--- pmars2/sim.c	Wed Oct 20 22:35:59 1999
***************
*** 202,208 ****
  void
  simulator1()
  {
! 
    /* range for random number generator */
    warrior_struct *oldW;                /* the previous living warrior to execute */
    ADDR_T  positions = coreSize + 1 - (separation << 1);
--- 202,210 ----
  void
  simulator1()
  {
! #ifdef PERMUTATE
!   int permidx = 0, permtmp, *permbuf = NULL;
! #endif
    /* range for random number generator */
    warrior_struct *oldW;                /* the previous living warrior to execute */
    ADDR_T  positions = coreSize + 1 - (separation << 1);
***************
*** 232,237 ****
--- 234,248 ----
    ADDR_T FAR *offsPtr;                /* temporary pointer used in op decode phase */
  #endif
  
+ #ifdef PERMUTATE
+   if (SWITCH_P) {
+     permbuf = (int *) malloc((size_t)(warriors * positions * sizeof(int)));
+     if (!permbuf) {
+       errout(outOfMemory);
+       Exit(MEMERR);
+     }
+   }
+ #endif
  
  #ifdef DOS16
    if (!alloc_p) {
***************
*** 279,284 ****
--- 290,299 ----
      (SWITCH_F - separation) :        /* seed from argument */
    /* seed from either checksum or time */
      rng(SWITCH_f ? checksum_warriors() : time(0));
+ #ifdef PERMUTATE
+   if (SWITCH_F && SWITCH_P)
+     seed *= warriors; /* get table index from position */
+ #endif
  
    display_init();
    round = 1;
***************
*** 295,300 ****
--- 310,327 ----
      cycle = cycles2;
      if (warriors > 1) {
        if (warriors == 2) {
+ #ifdef PERMUTATE
+         if (SWITCH_P) {
+           if (permidx == 0) { /* initialize buffer */
+             for (;permidx < warriors*positions; permidx++)
+               permbuf[permidx] = permidx;
+           }
+           permtmp = seed % permidx;
+           warrior[1].position = separation + permbuf[permtmp]/warriors;
+           starter = warrior + permbuf[permtmp] % warriors;
+           permbuf[permtmp] = permbuf[--permidx];
+         } else
+ #endif
          warrior[1].position = separation + seed % positions;
          seed = rng(seed);
        } else {
***************
*** 1193,1198 ****
--- 1220,1231 ----
  #endif                                /* PSPACE */
        default:
          errout(fatalErrorInSimulator);
+ #ifdef PERMUTATE
+         if(permbuf) {
+           free(permbuf);
+           permbuf = NULL;
+         }
+ #endif
  #ifndef DOS16
          /* DOS taskQueue may not be free'd because of segment wrap-around */
          free(memory);
***************
*** 1242,1247 ****
--- 1275,1286 ----
    } while (++round <= rounds);
  
    display_close();
+ #ifdef PERMUTATE
+   if(permbuf) {
+     free(permbuf);
+     permbuf = NULL;
+   }
+ #endif
  #ifndef DOS16
    /* DOS taskQueue may not be free'd because of segment wrap-around */
    free(memory);
diff -c pmars1/str_eng.c pmars2/str_eng.c
*** pmars1/str_eng.c	Tue Feb 20 13:15:50 1996
--- pmars2/str_eng.c	Wed Oct 20 22:35:59 1999
***************
*** 405,410 ****
--- 405,413 ----
  #ifdef PSPACE
  char   *optPSpaceSize = "Size of P-space [1/16th core]";
  #endif
+ #ifdef PERMUTATE
+ char   *optPermutate = "Permutate starting positions";
+ #endif
  #if defined(XWINGRAPHX)
  char   *optXOpt[] = {
    "Display to connect to",
***************
*** 421,426 ****
--- 424,432 ----
  char   *badScoreFormula = "\nBad score formula\n";
  #ifdef PSPACE
  char   *pSpaceTooBig = "\nP-space is bigger than core\n";
+ #endif
+ #ifdef PERMUTATE
+ char   *permutateMultiWarrior = "\nPermutation cannot be used in multiwarrior battles\n";
  #endif
  /* These strings are used by the VMS Language Sensitive Editor */
  #ifdef VMS
