/*
 *  File:    AdjacentCorner.cpp
 *  Author:  S Harry White
 *  Created: 2011-04-24
 *  Updated: 2020-04-29
 *    Add howMany.
 *  Updated: 2020-06-27
 *    Add makeDeLaHire.
 *    Add input selection of method.
 *    Sort output in Frénicle standard form removing duplicates.
 *  Updated: 2021-12-29
 *    Replace & with && in one piece of code.
 */

/*
 *  Makes adjacent corner paired magic squares of doubly even order n>=4.
 */

#include "stdafx.h"
#include <assert.h>
#include <conio.h>
#include <direct.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <Windows.h>

int **xSquare=NULL, **bSquare=NULL, **Squares=NULL, *square=NULL, 
    *tSide=NULL, *bSide=NULL, *lSide=NULL, *rSide=NULL;
bool *numberUsed=NULL; const bool F=false, T=true;
const int startSize=12, startSquaresSize=1024;
int allocatedSize, allocatedSquaresSize, biggestValue, Sindex, sLen;
//================================ allocate store ==================================

char *storeAllocFail="Storage allocation failed"; bool bell=T;
bool reportError(char *msg) {
//   -----------
  printf("%sError: %s.\n", bell ? "\a\n" : "",  msg);
  if (bell) bell=F; return F;
} // reportError

void freeInts(int **line) { if (*line!=NULL) { free(*line); *line=NULL; }}
//   --------

void freeSquare(int*** square, const int size) {
//   ----------
  if (*square!=NULL) {
    for (int i=0; i<size; i++) free((*square)[i]);
    free(*square); *square=NULL;
  }
} // freeSquare

void freeStore() {
//   ---------
  freeSquare(&xSquare, allocatedSize); freeSquare(&bSquare, allocatedSize);
  freeSquare(&Squares, allocatedSquaresSize); freeInts(&square); 
  freeInts(&tSide); freeInts(&bSide); freeInts(&lSide); freeInts(&rSide);
  if (numberUsed!=NULL) { free(numberUsed); numberUsed=NULL; }
  allocatedSize=0;
} // freeStore

bool allocateInts(int **line, const int size) {
//   ------------
  *line=(int*)malloc(size*sizeof(int)); return *line!=NULL;
} // allocateInts

bool allocateSquare(int*** square, const int size) {
//   --------------
  bool ok; *square=(int**) malloc(size*sizeof(int*)); ok=(*square!=NULL);
  if (ok) {
    int numAllocated=size;
    for(int i=0; i<size; i++) {
      int *p=(int*) malloc(size*sizeof(int));
      (*square)[i]=p;
      if (p==NULL) { numAllocated=i; ok=F; break; }
    }
    if (!ok) freeSquare(square, numAllocated);
  }
  return ok;
} // allocateSquare

bool allocateSquares(const int size) {
//   ---------------
  bool ok; int length=size*size;
  Squares=(int**) malloc(startSquaresSize*sizeof(int*)); ok=(Squares!=NULL);
  if (ok) {
    int numAllocated=startSquaresSize;
    for(int i=0; i<startSquaresSize; i++) {
      int *p=(int*) malloc(length*sizeof(int));
      (Squares)[i]=p;
      if (p==NULL) { numAllocated=i; ok=F; break; }
    }
    if (!ok) freeSquare(&Squares, numAllocated);
  }
  return ok;
} // allocateSquares

bool increaseSquares() {
//   ---------------
  bool ok;
  int length=allocatedSize*allocatedSize,  // of square
      size=allocatedSquaresSize+allocatedSquaresSize,
      **t=(int**) malloc(size*sizeof(int*));
  if (ok=(t!=NULL)) {
    for (int i=0; i<allocatedSquaresSize; i++) t[i]=Squares[i];
    free(Squares); Squares=t;
    int numAllocated=size;
    for(int i=allocatedSquaresSize; i<size; i++) {
      int *p=(int*) malloc(length*sizeof(int));
      (Squares)[i]=p;
      if (p==NULL) { numAllocated=i; ok=F; break; }
    }
    if (!ok) freeSquare(&Squares, numAllocated);
  }
  if (ok) allocatedSquaresSize=size; else reportError(storeAllocFail);
  return ok;
} // increaseSquares

bool allocateStore(int size) {
//   -------------
  bool ok=T; if (size<startSize) size=startSize;
  if (size>allocatedSize) {
    freeStore();
    if (ok=allocateSquare(&xSquare, size))
      if (ok=allocateSquare(&bSquare, size))
        if (ok=allocateSquares(size)) {
          allocatedSize=size; allocatedSquaresSize=startSquaresSize;
          if (ok=allocateInts(&square, size*size))
            if (ok=allocateInts(&tSide, size))
              if (ok=allocateInts(&bSide, size))
                if (ok=allocateInts(&lSide, size))
                  if (ok=allocateInts(&rSide, size))
                    if (ok) ok=(numberUsed=(bool *) malloc((size*size+1)*sizeof(bool)))!=NULL;
        
    }
    if (!ok) freeStore();
  }
  return ok;
} //allocateStore
//========================================= check squares =======================================

bool isCorrect(int **x, const int n) {
//   ---------
  const int nn=n*n, nnp1=nn+1, chkSum= n/2*nnp1; if (biggestValue!=(nn/2)) return F;
  int sumX, sumY, sumXY=0, sumYX=0;

  for (int i=0; i<n; i++) {
    sumX=0; sumY=0; for (int j=0; j<n; j++) { sumX+=x[i][j]; sumY+=x[j][i]; }
    if ((sumX!=chkSum)|(sumY!=chkSum)) return F; sumXY+=x[i][n-i-1]; sumYX+=x[i][i];
  }
  return ((sumXY==chkSum)&(sumYX==chkSum));
} // isCorrect

bool isAdjacent(int **x, const int n) {
//   ----------
  const int m=n-1, l=n-2, S2=n*n+1; int v;

  // corners
  v=x[0][0]; if (v+x[1][1]!=S2) return false;
  v=x[0][m]; if (v+x[1][m-1]!=S2) return false;
  v=x[m][0]; if (v+x[m-1][1]!=S2) return false;
  v=x[m][m]; if (v+x[m-1][m-1]!=S2) return false;

  for (int i=1; i < m; ++i) { // rest of top, bottom, left, right
    v=x[0][i]; if ((v+x[1][i-1]!=S2)&&(v+x[1][i+1]!=S2)) return false;
    v=x[m][i]; if ((v+x[m-1][i-1]!=S2)&&(v+x[m-1][i+1]!=S2)) return false;
    v=x[i][0]; if ((v+x[i-1][1]!=S2)&&(v+x[i+1][1]!=S2)) return false;
    v=x[i][m]; if ((v+x[i-1][m-1]!=S2)&&(v+x[i+1][m-1]!=S2)) return false;
  }

  for (int r=1; r < m; ++r) for (int c=1; c < m; ++c) { 
    v=x[r][c];
    if ((v+x[r-1][c-1]!=S2)&&(v+x[r-1][c+1]!=S2)&&(v+x[r+1][c-1]!=S2)&&(v+x[r+1][c+1]!=S2))
      return false;
  }
  return true;
} // isAdjacent
//========================================= output squares =======================================

int fieldWidth(const int n) {
//  ----------
  if (n==1) return 1; int i=n*n, width=1; while ((i/=10)!=0) ++width; return width;
} // fieldWidth

typedef bool (*t_fprintFW)(FILE *fp, const int i);

bool fprintFW1(FILE *fp, const int i) { return fprintf(fp, "%1d",  i)>0; }
bool fprintFW2(FILE *fp, const int i) { return fprintf(fp, "%2d",  i)>0; }
bool fprintFW3(FILE *fp, const int i) { return fprintf(fp, "%3d",  i)>0; }
bool fprintFW4(FILE *fp, const int i) { return fprintf(fp, "%4d",  i)>0; }
bool fprintFW5(FILE *fp, const int i) { return fprintf(fp, "%5d",  i)>0; }
bool fprintFW6(FILE *fp, const int i) { return fprintf(fp, "%6d",  i)>0; }
bool fprintFW7(FILE *fp, const int i) { return fprintf(fp, "%7d",  i)>0; }
bool fprintFW8(FILE *fp, const int i) { return fprintf(fp, "%8d",  i)>0; }
bool fprintFW9(FILE *fp, const int i) { return fprintf(fp, "%9d",  i)>0; }
bool fprintFWa(FILE *fp, const int i) { return fprintf(fp, "%10d", i)>0; }

static t_fprintFW fprintFW[]={ NULL,
  fprintFW1, fprintFW2, fprintFW3, fprintFW4, fprintFW5,
  fprintFW6, fprintFW7, fprintFW8, fprintFW9, fprintFWa
};
const int maxFieldWidth=10;
bool printSquare(int **x, const int n, FILE *wfp) {
//   -----------
  const int fw0=fieldWidth(n), fw=fw0+1; if (fw>maxFieldWidth) return F;
  for (int i=0; i<n; i++) {
    if (!fprintFW[fw0](wfp, x[i][0])) return F;
    for (int j=1; j<n; j++)   
      if (!fprintFW[fw](wfp, x[i][j])) return F;
    if (fputc('\n', wfp)==EOF) return F;
  }
  return fputc('\n', wfp)!=EOF;
} // printSquare

bool outputSquares(const int n, FILE *wfp) {
//   -------------
  const int m=n-1, fw0=fieldWidth(n), fw=fw0+1; if (fw>maxFieldWidth) return F;

  for (int i=0; i<Sindex; i++) {
    int *x=Squares[i], j=0, r=n, c;
    while (r--) {
      if (!fprintFW[fw0](wfp, x[j++])) return F;
      c=m; while (c--) if (!fprintFW[fw](wfp, x[j++])) return F;
      if (fputc('\n', wfp)==EOF) return F;
    }
    if (fputc('\n', wfp)==EOF) return F;
  }
  return T;
} // outputSquares
//================================= sort Frénicle ascending =================================

int cmpSquares(int *key, int *s) {
//  ----------
  int i=0;
  while(i++<sLen) if (*key<*s) return -1; else if (*key++>*s++) return 1; return 0;
} // cmpRowPerms

int findSquare(int *key, int *insertPoint) {
//  ----------
  int first=0, last=Sindex-1, middle;

  while (first<=last) {
    middle=(first+last)/2; int cmp=cmpSquares(key,Squares[middle]);
    if (cmp<0) last=middle-1; else if (cmp>0) first=middle+1; else return T;
  }
  *insertPoint=first; return F;
} // findSquare

bool insertSquare(int *sq, const int insertPoint, bool *storeFail) {
//   ------------
  if (Sindex==allocatedSquaresSize) if (!increaseSquares()) { *storeFail=T; return F; }
  int *p=Squares[Sindex];
  for (int i=Sindex; i>insertPoint; --i) Squares[i]=Squares[i-1];
  for (int i=0; i<sLen; ++i) p[i]=sq[i]; Squares[insertPoint]=p; ++Sindex; return T;
} // insertSquare

bool pushSquare(int **x, const int n, bool *storeFail) {
//   ----------
  int i=0, insertPoint;

  for (int r=0; r<n; ++r) for (int c=0; c<n; ++c) square[i++]=x[r][c];
  if (Sindex==0) insertPoint=0; else if (findSquare(square, &insertPoint)) return F;
  return insertSquare(square, insertPoint, storeFail);
} // pushSquare

#define fForm(iX, jX) for (int i=0; i<n; ++i) for (int j=0; j<n; ++j) t[iX][jX]=x[i][j]
#define xCopy() for (int i=0; i<n; ++i) for (int j=0; j<n; ++j) x[i][j]=t[i][j]

void putInFrenicleForm(int **x, const int n) {
//   -----------------
  const int m=n-1, l=n-2; bool inFrenicleForm=F;
  int **t=bSquare, minC=min(min(x[0][0], x[0][m]), min(x[m][0], x[m][m]));

  if (x[0][0]==minC) {
    if (x[0][1]<x[1][0]) inFrenicleForm=T;         else fForm(j,i);     /* YX */
  } else if (x[0][m]==minC) {
    if (x[1][m]<x[0][l]) fForm(m-j,i);   /* -90 */ else fForm(i,m-j);   /* Y  */
  } else if (x[m][m]==minC) {
    if (x[m][l]<x[l][m]) fForm(m-i,m-j); /* 180 */ else fForm(m-j,m-i); /* XY */
  } else { // x[m][0]==minC
    if (x[l][0]<x[m][1]) fForm(j,m-i);   /* 90  */ else fForm(m-i,j);    /* X  */
  }
  if (!inFrenicleForm) xCopy();
} // putInFrenicleForm

bool putSquare(int **x, const int n) {
//   ---------
  bool storeFail=F;
  putInFrenicleForm(x,n); pushSquare(x, n, &storeFail); return !storeFail;
} // putSquare
//======================================= common procedures ======================================

void seed_rand() { srand((unsigned int)time(NULL)); }

int random(const int x) { return rand()%x; }

bool randomBool() { return random(2)==0; }
//========================================= double border ========================================

typedef void (*t_Turn)(int **, int**, const int, const int, const int);
void no_Turn   (int **x, int** b, const int n, const int i, const int j) { x[i][j]    =b[i][j]; };
void rotate_90 (int **x, int** b, const int n, const int i, const int j) { x[j][n-i]  =b[i][j]; };
void rotate_180(int **x, int** b, const int n, const int i, const int j) { x[n-i][n-j]=b[i][j]; };
void rotate_270(int **x, int** b, const int n, const int i, const int j) { x[n-j][i]  =b[i][j]; };
void rotate_Y  (int **x, int** b, const int n, const int i, const int j) { x[i][n-j]  =b[i][j]; };
void rotate_XY (int **x, int** b, const int n, const int i, const int j) { x[n-j][n-i]=b[i][j]; };
void rotate_X  (int **x, int** b, const int n, const int i, const int j) { x[n-i][j]  =b[i][j]; };
void rotate_YX (int **x, int** b, const int n, const int i, const int j) { x[j][i]    =b[i][j]; };
static t_Turn turnCell[]={ no_Turn,  rotate_90, rotate_180, rotate_270,
                             rotate_Y, rotate_XY, rotate_X,   rotate_YX };
void Turn(int **x, int **b, const int o, const int n) {
//   ----
  const int numRotations=8;
  int r, c; const int nmo=n-o, npo=n+o, k=random(numRotations);

  if (nmo<7) { // turn all 4, 5, 6, 7
    for (r=o; r<=n; r++) for (c=o; c<=n; c++)
      turnCell[k](x, b, npo, r, c);
  } else { // turn only 2 border rows and columns
    int p=o+1, m=n-1;
    for (r=o; r<=n; r+=nmo) for (c=o; c<=n; ++c)
      turnCell[k](x, b, npo, r, c);
    for (c=o; c<=n; c+=nmo) for (r=p; r<n; ++r)
      turnCell[k](x, b, npo, r, c);

    for (r=p; r<=m; r+=(nmo-2)) for (c=p; c<=m; ++c)
      turnCell[k](x, b, npo, r, c);
    for (c=p; c<=m; c+=(nmo-2)) for (r=p; r<m; ++r)
      turnCell[k](x, b, npo, r, c);
  }
} // Turn

void makeActual(int **x, const int n) {
//   ----------
  const int pPlus= n*n/2, mPlus=pPlus+1;

  for (int i=0; i<n; i++) for (int j=0; j<n; j++) x[i][j]+=(x[i][j]>0) ? pPlus : mPlus;
} // makeActual

const int num4x4a=48;
int code4x4a[]={
0x03dcf17a,0x03dcf1b6,0x03ecf279,0x03ecf2b5,0x05baf17c,0x05baf1d6,0x05eaf479,0x05eaf4d3,
0x06b9f27c,0x06b9f2e5,0x06d9f47a,0x06d9f4e3,0x12cde06b,0x12cde0a7,0x12fde368,0x12fde3a4,
0x14abe06d,0x14abe0c7,0x14fbe568,0x14fbe5c2,0x17a8e36d,0x17a8e3f4,0x17c8e56b,0x17c8e5f2,
0x21ced05b,0x21ced097,0x21fed358,0x21fed394,0x249bd0c7,0x24fbd658,0x24fbd6c1,0x2798d3f4,
0x27c8d65b,0x27c8d6f1,0x30dfc14a,0x30dfc186,0x30efc249,0x30efc285,0x358ac1d6,0x35eac749,
0x35eac7d0,0x3689c2e5,0x36d9c74a,0x36d9c7e0,0x41feb538,0x42fdb638,0x50efa429,0x53eca729
};

void swapBorder(int **b, const int o, const int n) {
//   -----------
  if (randomBool()) {
    const int p=o+1, m=n-1; int t;
    for (int c=o; c<=n; ++c) {
      t=b[o][c]; b[o][c]=b[p][c]; b[p][c]=t; t=b[n][c]; b[n][c]=b[m][c]; b[m][c]=t;
    }
    for (int r=o; r<=n; ++r) {
      t=b[r][o]; b[r][o]=b[r][p]; b[r][p]=t; t=b[r][n]; b[r][n]=b[r][m]; b[r][m]=t;
    }
  }
} // swapBorder

void putCenter4x4(int **x, int **b, const int o, const int n) {
//   ------------
  int code=code4x4a[random(num4x4a)]; const int Msum=34; // 4*(4*4+1)/2;

  x[2][2]=(code&0xf)+1;  code>>=4; x[2][0]=(code&0xf)+1;  code>>=4;
  x[1][2]=(code&0xf)+1;  code>>=4; x[1][1]=(code&0xf)+1;  code>>=4;
  x[1][0]=(code&0xf)+1;  code>>=4; x[0][2]=(code&0xf)+1;  code>>=4;
  x[0][1]=(code&0xf)+1;  code>>=4; x[0][0]=(code&0xf)+1;

  x[0][3]=Msum-x[0][0]-x[0][1]-x[0][2]; x[1][3]=Msum-x[1][0]-x[1][1]-x[1][2];
  x[3][0]=Msum-x[0][0]-x[1][0]-x[2][0]; x[3][2]=Msum-x[0][2]-x[1][2]-x[2][2];
  x[3][3]=Msum-x[0][0]-x[1][1]-x[2][2]; x[3][1]=Msum-x[3][0]-x[3][2]-x[3][3];
  x[2][1]=Msum-x[0][1]-x[1][1]-x[3][1]; x[2][3]=Msum-x[2][0]-x[2][1]-x[2][2];

  for (int i=0; i<4; i++) for (int j=0; j<4; j++)
    b[i+o][j+o]=x[i][j]-(x[i][j]>8 ? 8 : 9); // (4*4+1)/2; (8.5)
  Turn(x, b, o, n);
} // putCenter4x4

void putBorder(int **x, int **b, const int o, const int n) {
//   ---------
  int *top=tSide, *bot=bSide, *lt=lSide, *rt=rSide, length=n-o-3; // choices in top, bot
  const int m=n-1, p=o+1;
  for (int c=o+2; c<m; c+=2) {
    int d=c+1, i=random(length);
    if (i%2) --i; int v;
    v=top[i];   b[o][c]=v; b[p][d]=-v; v=top[i+1]; b[o][d]=v; b[p][c]=-v;
    v=bot[i];   b[n][c]=v; b[m][d]=-v; v=bot[i+1]; b[n][d]=v; b[m][c]=-v;
    for (int j=i; j<length; ++j) { top[j]=top[j+2]; bot[j]=bot[j+2]; } length-=2;
  }

  length=n-o-3; // choices in lt, rt
  for (int r=o+2; r<m; r+=2) {
    int s=r+1, i=random(length);
    if (i%2) --i; int v;
    v=rt[i];   b[r][n]=v; b[s][m]=-v; v=rt[i+1]; b[s][n]=v; b[r][m]=-v;
    v=lt[i];   b[r][o]=v; b[s][p]=-v; v=lt[i+1]; b[s][o]=v; b[r][p]=-v;
    for (int j=i; j<length; ++j) {rt[j]=rt[j+2]; lt[j]=lt[j+2];} length-=2;
  }
  swapBorder(b, o, n); Turn(x, b, o, n);
} // putBorder

void makeDoubleBorder(int **x, int **b, const int size) {
//   ----------------
  int v=9; // (4*4+1)/2; (8.5)

  // fill center 4x4
  int o=(size-4)/2, n=o+3; putCenter4x4(x, b, o, n); 
  for (int i=8; i<=size; i+=4) {
    int ct=0, cb=0, rl=0, rr=0; o=(size-i)/2;  n=o+i-1; const int p=o+1, m=n-1;
    b[o][o]=-v; b[p][p]=v++; /* NW */ b[p][m]=-v; b[o][n]=v++; /* NE */
    b[m][p]=-v; b[n][o]=v++; /* SW */ b[n][n]=-v; b[m][m]=v++; /* SE */
    b[n][p]=-v; b[m][o]=v++; /* SW */ b[m][n]=-v; b[n][m]=v++; /* SE */
    b[p][o]=-v; b[o][p]=v++; /* NW */ b[o][m]=-v; b[p][n]=v++; /* NE */

    const int k=(i-4)/4; int *top=tSide, *bot=bSide, *lt=lSide, *rt=rSide;
    int j=k; while (j--) {
      top[ct++]= v++; top[ct++]=  v+2;  top[ct++]=-v++; top[ct++]=-v; v+=2;
      bot[cb++]=-v++; bot[cb++]=-(v+2); bot[cb++]= v++; bot[cb++]= v; v+=2;
      rt[rr++] = v++; rt[rr++] =  v+2;  rt[rr++] =-v++; rt[rr++] =-v; v+=2;    
      lt[rl++] =-v++; lt[rl++] =-(v+2); lt[rl++] = v++; lt[rl++] = v; v+=2;
    }
    putBorder(x, b, o, n);
  } // for (i=8; ...
  biggestValue=v-1; makeActual(x, size);
}  // makeDoubleBorder
//======================================= de la Hire ======================================

void makeDeLaHire(int **x, int **t, const int n) {
//   ------------
  const int m=n-1, o=n+1, g=n/2; bool *u=numberUsed;

  for (int i=0; i<=n; ++i) u[i]=F;
  for (int r=0; r<n; r+=2) {
    int i=random(n)+1, j; while(u[i]) i=random(n)+1; j=o-i; u[i]=T; u[j]=T;
    for (int c=0; c<g; ++c) { x[r][c]=i; x[r+1][c+g]=i; x[r][c+g]=j; x[r+1][c]=j; }
  }
  for (int i=0; i<=n; ++i) u[i]=F;
  for (int c=0; c<n; c+=2) {
    int i=random(n), j; while(u[i]) i=random(n); j=m-i; u[i]=T; u[j]=T;
    for (int r=0; r<g; ++r) { t[r][c]=i; t[r+g][c+1]=i; t[r][c+1]=j; t[r+g][c]=j; }
  }
  for (int r=0; r<n; ++r) for (int c=0; c<n; ++c) x[r][c]+=n*t[r][c];
  biggestValue=n*n/2; // checked in isCorrect
} // makeDeLaHire
//====================================== make squares =======================================

const char *notMagic =
  "\a\nERROR: Square is NOT magic! Please report by email\n";
const char *notAdjacent =
  "\a\nERROR: Square is NOT adjacent paired! Please report by email\n";

bool makeEven(const int n, const int kind) {
//   --------
  int **x=xSquare, **b=bSquare;
  if (kind==1) makeDoubleBorder(x, b, n); else makeDeLaHire(x, b, n);
  if (isCorrect(x, n)) { if (!isAdjacent(x, n)) printf(notAdjacent); } else printf(notMagic);
  return putSquare(x, n);
} // makeEven
//========================================== input ==========================================

void clearLine(int c) { while (c!='\n') c=getchar(); }
//   ---------

bool getY() {
//   ----
  int c;  do { c=getchar(); } while ((c==' ')|(c=='\t')|(c=='\n'));
  clearLine(c); return (c=='Y')|(c=='y');
}

bool getYorOrder(int *n) { // 'y', 'n' or the order
//   -----------
  bool result=F; int c; *n=0;

  do { c=getchar(); } while ((c==' ')|(c=='\t')|(c=='\n') );
  if ( (c=='Y')|(c=='y') ) result=T;
  else if ( (c!='N')&(c!='n') )
    if ( ('1'<=c)&(c<='9') ) {
      int i=c-'0'; while ( ('0'<=(c=getchar()))&&(c<='9') ) i=i*10+c-'0'; *n=i; result=T;
    }   
  clearLine(c); return result;
} // getYorOrder

int getInt() {   int n=0; scanf_s("%d", &n); clearLine(getchar()); return n; }
//  -------
//================================================== output ===============================================

const int bufSize=1024;
bool openDir() {
//   -------
  char buf[bufSize], msg[bufSize]; const char *baseName="AdjacentCornerSquares";
  strcpy_s(buf, bufSize, baseName); int sub=0;
  do {
    if (_mkdir(buf)==0) break;
    if (errno!=EEXIST) { sprintf_s(msg, bufSize, "Can't make folder %s", buf); perror(msg); return F; }
    sprintf_s(buf, bufSize, "%s_%d", baseName, ++sub);
  } while (T);
  if (_chdir(buf)!=0) { sprintf_s(msg, bufSize, "Can't open folder %s", buf); perror(msg); return F; }
  printf("Output files are in folder %s\n\n", buf); return T;
} // openDir

FILE *open_File(const int n) {
//    ---------
  FILE *wfp=NULL; char buf[bufSize]; sprintf_s(buf, bufSize, "Order%d.txt", n);
  if (fopen_s(&wfp, buf, "a")!=0) {
    char msg[bufSize]; sprintf_s(msg, bufSize, "\a\nCan't open for write %s", buf); perror(msg);
  }
  return wfp; 
} // open_File
//================================================= main ==================================================

bool validOrder(const int n) {
//   ----------
  if ((n<=0)|(n%4!=0)) {
    printf("\aError: %d is not a positive integral multiple of 4.\n", n);
    return F;  
  }
  return T;
} // validOrder

int inputKind() {
//  ---------
  int k=1; printf("Method, ( 1 double border, 2 de la Hire)? ");
  k=getInt(); if ((k<1)|(k>2)) k=1; return k;
} // inputKind

int main() {
//  ----
  bool ok=F;
  if (openDir()) {
    int n=0; bool another=T, inputSize=T, writeError=F; seed_rand(); 
    do {     
      if (inputSize) { printf("\nInput the order of the square: "); n=getInt(); }
      if (validOrder(n)) {
	      if (allocateStore(n)) {
	        FILE *wfp=NULL;
          if ( (wfp=open_File(n))!=NULL) {
            int kind=inputKind(); Sindex=0; sLen=n*n;
            int howMany=1; printf("\nHow many? "); howMany=getInt();
            int loop=max(howMany,1000000); 
            while (loop--) {
              ok=makeEven(n, kind); if (!ok) break; if (Sindex==howMany) break;
            }
            if (ok) writeError=!outputSquares(n, wfp); fclose(wfp);
	        }
	      } else printf("\a\nERROR: Storage allocation failed.\n");
      }
      if (writeError) { perror("\a\nError writing file"); another=F; }
      else {
        printf("\nMake another square? "
          "input y (yes) or n (no) or the order of the square: ");
        if (getYorOrder(&n)) inputSize=(n==0); else another=F;
      }
    } while (another);
    freeStore();
  }
  printf("\nPress a key to close the console.");
  while (!_kbhit()) Sleep(250); return ok?EXIT_SUCCESS:EXIT_FAILURE;
} // main