#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <stdint.h>
#include <limits.h>
#include <time.h>
#include <sys/stat.h>
static time_t begtime;
static time_t endtime;
#include <sys/time.h>
static struct itimerval it[3],ot;
#define ABS(a) (((a) > 0) ? (a) : (-(a)))
#define MINI(a,b) ((a)<=(b)?(a):(b))
#define MAXI(a,b) ((a)>=(b)?(a):(b))

#if defined(DARWIN) || defined(FREEBSD)
#else
#include <malloc.h>
#endif

static char *elements[] = {
	"Bq","H","He","Li","Be","B","C","N","O","F","Ne",
	"Na","Mg","Al","Si","P","S","Cl","Ar",
	"K","Ca","Sc","Ti","V","Cr","Mn","Fe","Co","Ni","Cu",
	"Zn","Ga","Ge","As","Se","Br","Kr",
	"Rb","Sr","Y","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag",
	"Cd","In","Sn","Sb","Te","I","Xe",
	"Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy",
	"Ho","Er","Tm","Yb","Lu","Hf","Ta","W","Re","Os","Ir","Pt",
	"Au","Hg","Tl","Pb","Bi","Po","At","Rn",
	"Fr","Ra","Ac","Th","Pa","U","Np","Pu","Am","Cm","Bk","Cf","X"};

static char *elemts[] = { " H","He",
      "Li","Be"," B"," C"," N"," O"," F","Ne",
      "Na","Mg","Al","Si"," P"," S","Cl","Ar",
      " K","Ca","Sc","Ti"," V","Cr","Mn","Fe","Co","Ni","Cu",
      "Zn","Ga","Ge","As","Se","Br","Kr",
      "Rb","Sr"," Y","Zr","Nb","Mo","Tc","Ru","Rh","Pd","Ag",
      "Cd","In","Sn","Sb","Te"," I","Xe",
      "Cs","Ba","La","Ce","Pr","Nd","Pm","Sm","Eu","Gd","Tb","Dy",
      "Ho","Er","Tm","Yb","Lu","Hf","Ta"," W","Re","Os","Ir","Pt",
      "Au","Hg","Tl","Pb","Bi","Po","At","Rn",
      "Fr","Ra","Ac","Th","Pa"," U","Np","Pu","Am","Cm","Bk","Cf",
      "XX","  "};

#define MXEL 100
typedef struct {
                 double vdwr[MXEL];
                 double vrad[MXEL];
                 int icol[MXEL];
               } ELMSTRU;

static ELMSTRU *elmptr;

static char *AminoAcids[] = {"GLY","ALA","SER","CYS","THR","ILE","VAL","MET",
"ASP","ASN","LEU","LYS","GLU","GLN","PRO","ARG","HIS","PHE","TYR","TRP",
"ASX","GLX","HYP","A","C","G","T","U","1MA","5MC","OMC","1MG","2MG","M2G",
"7MG","OMG","YG","I","+U","H2U","5MU","PSU"};
static char *AAlet[] = {"G","A","S","C","T","I","V","M","D","N","L","K","E",
"Q","P","R","H","F","Y","W","?","?","?","A","C","G","T","U","?","?","?","?","?","?","?","?","?","I","?","?","?","?"};

static char *ForceFields[] = {"No Force Field","Tinker MM3","Tinker Charmm","Tinker Amber","Tink AmoebaPRO","Sybyl","Quanta Charmm","Amber/GAFF","PMF","Gromacs","Gromacs2","Gromos96"};

static int SI(const void *a, const void *b)
{
  return (*(int*)a - *(int*)b);
}

typedef struct { int iun1;
		 int iun2;
		 int iun3;
		 int iun4;
		 int iun5;
               } FNIUNSTRU;

static FNIUNSTRU *fniun;

#define PI   3.14159265358979323846

#define MXAMB 1590
#define MXGFF  72
#define MXAMBC 49
typedef struct { double ambchg[MXAMB];
                 double ambvw1[MXAMBC];
                 double ambvw2[MXAMBC];
                 double gfvdw[MXGFF][2];
                 int ambvdt[MXAMB];
                 double cysneg[9];
               } CHGVDWSTRU;

static CHGVDWSTRU *chgvdwptr;

static char  *gffext[MXGFF];
static int Ngffext = 0;
static char *mldfile;
static char  *exepath[1];
static int Nexepath = 0;
static int INVESTIGATE = 0;
#define MAXGLUT 100
static int nglut = 0;
static int GLUTH[MAXGLUT];
static int GLUTCO[MAXGLUT];
static int nnhp = 0;
static int ANHP[MAXGLUT];
static int nco = 0;
static int ACO[MAXGLUT];


static int NW_MKBACK = 0;

#define NUMAT 20000
#define MXCON 10

typedef struct { double coo[NUMAT][3];
		 double rzp[NUMAT];
		 int ianz[NUMAT];
		 int iaton[NUMAT];
		 int iatclr[NUMAT];
		 int iresid[NUMAT];
		 int ixp[NUMAT];
		 int iyp[NUMAT];
		 int iconn[NUMAT][MXCON+1];
		 int icont[NUMAT];
               } ATOMSTRU;

static ATOMSTRU *atomptr;

typedef struct { int iener;
                 float energy;
                 int lig[3];
                 int prot[3];
                 int conf;
                } ENERSTRU;

static ENERSTRU *eneptr;

#define MAXSTRLEN 80
#define MAXSTRLMW 80
#define MAXPATHLEN 1024
#define MAXCMD 256
#define MAXCMD5 512
#define MXSYM 103
#define MXHSYM 64
#define SUBLEN1 80
#define MXSTRFOR 137
#define TOANG 0.52917706
static int tmpon = 0;
static char home_dir[MAXSTRLEN] = " ";
static char molden_root[MAXSTRLEN] = " ";
static char molden_rootb[MAXSTRLEN] = " ";
static char dckout[MAXPATHLEN] = "dock.mol2";

#define MEXCL 10

typedef struct { double qexcl[MEXCL];
                 int ianexc[MEXCL];
                } METSTRU;

static METSTRU *mets;

#define NUMATM 2000
typedef struct { double xyz[NUMATM][3];
        } XYZSTRU;
static XYZSTRU *XYZ;

#define MXCHAI 50
#define MXRES 42
#define MXHETA 150

typedef struct { int Allocated[MXHETA];
                 char  *HetAtm[MXHETA];
                 int NHetAtm;
                } HETATMSTRU;
static HETATMSTRU hetptr = {.Allocated = {0},.HetAtm = {NULL},.NHetAtm = 0};

#define MXHETLAB 5000
typedef struct { int iat[MXHETLAB];
                 char  *HetLab[MXHETLAB];
                 int NHetLab;
                } HETLABSTRU;
static HETLABSTRU hetlab = {.NHetLab = 0};

static char *pdbcode = NULL;
static char *pdbcbck = NULL;
static char firstfile[1024];
static int ipdb[MXSYM];
static int ihpdb[MXHSYM*3];
static char cmdstr[MAXPATHLEN];
static char strname[MAXSTRLEN];
static char stemp[MAXSTRLEN];
static char molwstr[MAXSTRLMW] = " ";
static char *tmpfil;
static int ATMselp = 0;
static int *jring;

void Calc_Overlap2();
void Calc_Overlap();
void Optimise_Overlap(int itri,
float *vdwr,float *vdwrl);
void Optimise_Energy(int itri,int mode,
float *q,float *vdwe, float *vdwr,
float *ql,float *vdwel,float *vdwrl,
int *iclos);

typedef struct {
        char *str;
        int *line_index;
        int *fpos;
        char **lines;
        int size;
        int nlines;
        int nfiles;
        int list;
        int opt;
        int currl; } FILEOP;

static FILEOP fileop = {NULL, NULL, NULL, 0, 0, 0, 0};

static char **mlftit = NULL;
static int mxtits = 0;
static int ntits = 0;

#define MXMFMOL 100

typedef struct { int nmols;
                 int imol;
                 int iendmf;
                 int ielin;
                 int maxmol;
                 int *mollin;
                } MFSTRU;

static MFSTRU *mfdata;

static volatile sig_atomic_t nomemf = 0;
static int *fftyp;
static int istruct = 0;
#define MAXSTRUCT 1

#define NUMADD 50000
static int addat = NUMADD;
static int *ipdbon;

#define MXMOL2 41
static char  *mol2[MXMOL2];
static int Nmol2 = 0;

static int ZERO = 0;
static int ONE = 1;
static int MONE = -1;
static int TWO = 2;
static int THREE = 3;
static int FOUR = 4;
static int FIVE = 5;
static int EIGHTEEN = 18;
static int FOURTYSEVEN = 47;
static int FOURTYNINE  = 49;
static int SEVENTYSEVEN = 77;

static char *ATYPE[] = {
        "    ",".1  ",".2  ",".3  ",".4  ",".ar ",".cat",
        ".am ",".pl3",".co2",".spc",".t3p",".O  ",".O2 "};

static int IHBT[] = {
        3     ,  1   ,  2   ,  3   ,  3   ,  4   ,  4   ,
        3     ,  3   ,  2   ,  3   ,  3   ,  2   ,  2 };


static char *ambstr[MXAMB];
static int Nambstr = 0;

static int ambatnr[] = {
7,6,6,1,8,1,7,6,6,1,8,1,6,1,7,6,6,1,8,1,
6,1,6,1,6,1,7,6,6,1,8,1,6,1,6,1,6,1,6,1,
7,6,6,1,8,1,6,1,6,1,6,1,6,1,7,6,6,1,8,1,
6,1,8,1,7,6,6,1,8,1,6,1,8,1,6,1,7,6,6,1,
8,1,6,1,16,1,7,6,6,1,8,1,6,1,16,7,6,6,8,1,
6,1,6,1,6,1,7,6,6,1,8,1,6,1,6,6,1,6,1,6,
1,7,6,6,1,8,1,6,1,6,6,1,6,1,6,8,1,7,6,6,
1,8,1,6,1,6,6,1,6,7,1,6,6,1,6,1,6,1,6,1,
7,6,6,1,8,1,6,1,6,7,1,6,1,6,1,7,1,7,6,6,
1,8,1,6,1,6,7,1,6,1,6,1,7,7,6,6,1,8,1,6,
1,6,7,6,1,6,1,7,1,7,6,6,1,8,1,6,1,6,8,7,
6,6,1,8,1,6,1,6,8,7,1,7,6,6,1,8,1,6,1,6,
1,6,8,7,6,6,1,8,1,6,1,6,1,6,8,7,1,7,6,6,
1,8,1,6,1,6,1,16,6,1,7,6,6,1,8,1,6,1,6,1,
6,1,6,1,7,1,7,6,6,1,8,1,6,1,6,1,6,1,7,1,
6,7,1,7,6,6,1,8,1,6,1,6,1,6,1,7,1,7,6,6,
1,8,6,1,7,6,6,1,8,1,6,1,6,1,6,8,6,1,8,6,
1,6,8,7,1,7,1,6,1,7,6,6,1,8,1,7,6,6,1,8,
1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,
6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,
1,8,1,7,6,6,1,8,1,6,1,7,6,6,1,8,1,7,6,6,
1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,
1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,
6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,
1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,
7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,
6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,
8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,8,1,7,
6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,
1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,
1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,
6,6,1,8,1,7,6,6,1,8,1,7,6,6,1,8,1,7,6,6,
1,8,1,7,6,6,1,8,8,1,3,11,19,37,55,12,20,30,17,
7,6,6,1,8,1,6,1,6,8,8,1,
7,6,6,1,8,1,6,1,6,1,6,8,8,1,
7,6,6,1,8,1,6,1,6,1,6,1,7,1,
299*0,
8,6,1,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,
6,7,6,7,6,1,7,1,1,1,8,6,1,1,6,1,8,6,1,6,
1,6,1,8,1,8,7,6,6,7,6,7,6,7,6,1,7,1,1,8,
1,8,6,1,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,7,
6,6,6,8,7,1,1,1,1,8,6,1,1,6,1,8,6,1,6,1,
6,1,8,1,8,7,6,7,6,6,6,8,1,8,1,1,8,6,1,1,
6,1,8,6,1,6,1,6,1,1,8,7,6,6,7,6,7,6,7,6,
1,7,1,1,1,8,6,1,1,6,1,8,6,1,6,1,6,1,1,8,
7,6,6,7,6,7,6,7,6,1,7,1,1,8,1,8,6,1,1,6,
1,8,6,1,6,1,6,1,1,8,7,6,7,6,6,6,8,7,1,1,
1,1,8,6,1,1,6,1,8,6,1,6,1,6,1,1,8,7,6,7,
6,6,6,8,1,8,6,1,1,15,8,8,1,8,15,8,8,1,8,15,
8,15,8,8,1,8,15,8,8,1,8,15,8,
8,6,1,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,6,7,6,7,6,1,7,1,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,7,6,6,6,1,8,7,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,8,7,6,8,7,6,7,1,6,1,6,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,6,1,7,6,7,1,6,8,6,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,6,7,6,7,6,8,1,1,7,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,6,7,6,7,6,8,1,1,7,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,8,7,6,6,7,6,7,6,7,6,8,1,1,7,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,6,7,6,7,6,7,6,8,7,6,6,1,6,1,6,1,6,1,6,1,6,1,6,8,8,6,1,7,1,6,8,8,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,7,6,6,6,8,8,1,1,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,7,6,7,6,6,6,8,8,1,1,6,1,
8,6,1,6,1,8,6,1,6,1,6,1,8,1,8,6,6,7,6,7,6,8,8,1,1,1
};

#define DCKDEBUG 0
#define DCKCOFF  10.0
#define DCKCMIN  1.5
#define DCKDEV   0.65
static float DCKdev = DCKDEV;
static char *dcklig;
static char *pdbfil;
static char *site;
static char sitestr[4];
static int dcksol = 20;
static int version12 = 0;
static int version34 = 0;
static int version5 = 0;
static int debugdck = DCKDEBUG;
static int FASTSLOW = 1;
static int ACTIVE_GROUPS = 4;
static double DCKCNT[3] =  {0.0,0.0,0.0};
static double LIGCNT[3] =  {0.0,0.0,0.0};
static int LCNT = -1;
static int NCLOS = -1;
static int DispLocal = 0;
static int DCKLIGPROC = 0;
static int DCKPROTPROC = -1;
static int DoDockCenter = 0;
static int DCKMETH = 0;
void CreateNPos(double *c1,double *c2,double *c3,double *c4);
void CreateCPos(double *c1,double *c2,double *c3,double *c4);
static char *pdbFile;
static int LigSel = 5;
static int UseOld = 0;
static float CNTDCK[3];
static float DCKRadius = 3.5;
static float OPTRadius = 10.0;
int  GetLig();
void ProcProtLig(int iop);
void ProcProt();

static float toangs = 0.52917706e0;

static int ncal = 0;

#define NUMCAL 50000
static int resinc[NUMCAL];
static char *achain[NUMCAL];
#define MXCHAI 50
#define MXRES 42
#define MXHETA 150
#define MXALN 20

typedef struct { 
		 int istiff;
		 int icalf[NUMCAL][6];
		 int ncalf;
		 int ianf[MXCHAI];
		 int islu[MXCHAI];
		 int nchain;
		 int iamino[NUMCAL];
		 int ihet[MXHETA];
		 int iclhet[MXHETA];
		 int reson[NUMCAL];
		 int issdon;
		 int icxp[NUMCAL];
		 int icyp[NUMCAL];
		 int iams[NUMCAL];
		 int ihets[MXHETA];
		 int ibck[4];
		 int isal[NUMCAL];
		 int irsnr[NUMCAL];
		 int lab[NUMCAL];
		 int ihashb;
		 int ishoh;
		 int ision;
		 int achain[NUMCAL];
		} CALFSTRU;

static CALFSTRU *calfptr;

typedef struct { int ihashz;
		 int ihetq[MXHETA];
		 int ihqset[MXHETA];
		 int ihhadd[MXHETA];
		 int labhet[MXHETA];
		 int ilcset;
		 int ligcat[MXHETA];
		} CLFSTRU;

static CLFSTRU *clfstrptr;

typedef struct { double *coo;
		 double *rzp;
		 double *qat;
		 int *isurf;
		 int *icont;
		 int *lwrit;
		 int *lring;
		 int *ianz;
		 int *iaton;
		 int *iatclr;
		 int *iresid;
		 int *ixp;
		 int *iyp;
		 int *iconn;
		 int *inat;
		 int *ityp;
		 int *ipdbt;
		 int *iclos;
		 int *mxnat;
		 int *iatoms;
		 int *ncont;
		 int mxorg;
               } COOSTRU;

static COOSTRU xyz;
static COOSTRU TMPxyz;
static COOSTRU DCKxyz;
static COOSTRU DCKtmp;
static COOSTRU CHKxyz;
static COOSTRU MOLxyz;
static COOSTRU DSTxyz;
static COOSTRU xyzbck;
static int DOCHK = 0;
static int ndocka;
static int nmolat;
static int MapConformers;
static int e12_calculated;
static int eint_calculated;
static COOSTRU *xyzp = &xyz;
static double *COOt = NULL;

typedef struct { COOSTRU coo;
		 CALFSTRU calf;
		 CLFSTRU clfstr;
		 XYZSTRU XYZ;
		 int ipoints;
		 HETATMSTRU  hetatm;
		 char **mlftit;
		 int ntits;
		 int mxtits;
		 char *fname;
		 char *pdbcode;
		 int iatoms;
		 int mxnat;
		 int pdb;
		 int backb;
		 int iftyp;
		 int natorg;
		 int mxzat;
		 int inact;
		 int inaf;
		 int atcol;
		 int ZMEAA;
		 int doesp;
		 int fftyp;
		 int irtcel;
		 int normc;
		 int icst;
		 int ibox;
		 int igfmap;
		 int iresrd;
		 int fancy;
		 int ihasex;
		 double uscl;
		 int ihasmf;
		 FILEOP memfil;
               } STRUSTRU;

static STRUSTRU *COO[MAXSTRUCT] = {NULL};

void Compress_Tri_L();

void safefree(void **pp)
{
   assert(pp);
   if (pp != NULL) {
	free(*pp);
	*pp = NULL;
   }
}

void ProcLig(int imode);

//  N = number of single bonds to rotate over
//  sng[1..N][0-1] two atoms of each single bond. Set in ProcLig
//  ityp gaff atom type of ligands atoms
//  NFRAG = number of fragments
//  ifrg[1..ndocka] = fragment number for each atom
//  SngFrg[1..N][0-1] the two atoms of each single bond, 
//                    the fragment number of each side [0] and [1]
//  FrgSngN[1..NFRAG] = number of rotatable bonds fragment is connected to
//  FrgSng[1..NFRAG][9] = for each fragment, the MAX 9 single bonds pointers
//                        the fragment is connected to
//  irsd[1..ndocka] = sp hybridisation number per atom, f.e. sp3 => 4
//                    SEE IHBT array
//  irng[1..ndocka] = is atom part of a ring =1

#define MXLIGA 40000
#define MXLTORS 9
static int mxliga = MXLIGA;

typedef struct {
		int N;
		int NFRAG;
		int irsd[MXLIGA];
		int irng[MXLIGA];
		int ring[MXLIGA];
		int extra;
		int jrng[MXLIGA];
		int ifrg[MXLIGA];
		int sng[MXLIGA][2];
		int dupsng[MXLIGA];
		int sngrot[MXLIGA];
		int SngFrg[MXLIGA][2];
		int FrgSng[MXLIGA][9];
		int FrgSngN[MXLIGA];
		int sngdone[MXLIGA];
		int sngnt[MXLIGA];
		int it[MXLIGA][MXLTORS][4];
		float trs1[MXLIGA][MXLTORS][4];
		float trs2[MXLIGA][MXLTORS][4];
		float trs3[MXLIGA][MXLTORS][4];
		float trs4[MXLIGA][MXLTORS][4];
		int ityp[MXLIGA];
		} SNGSTRU;

typedef struct {
		int type;
		int n;
		float v1[3];
		float v2[3];
		float polar1;
		float polar2;
		float azimuth1;
		float azimuth2;
		float polarb1;
		float polarb2;
		float azimuthb1;
		float azimuthb2;
		float radius;
		float rp;
		float maxarc[2];
		float ene;
		float chgsc[2];
		float dissc[2];
		float angsc[3];
		float center[3];
		int iden;
		} AREASTRU;

#define EHBOND  -2.35
#define EVDW    -0.35
#define RHBOND1  1.9
#define RHBOND2  1.8
#define RVDW1    4.0
#define RVDW2    4.5
#define RVDW3    4.8
#define DELHBOND 1.2
#define DELVDW   1.6


static AREASTRU AREAINI = {0,0,
			{.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND2,RHBOND2,{DELHBOND,DELHBOND},EHBOND,
			{0.0,0.0},{0.0,0.0},
			{0.0,0.0,0.0},{0.0,0.0,0.0},-1};

static AREASTRU COOmin = {1,3,
			{-1.0,0.0,0.0},{0.0,1.0,0.0},
			-50.0,50.0,40.0,80.0,130.0,230.0,40.0,80.0,
			RHBOND2,RHBOND2,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{20.0,60.0,1.0},{0.0,0.0,0.0},0};

static AREASTRU CO = {2,2,
			{-1.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,70.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{5.0,70.0,1.0},{0.0,0.0,0.0},1};

static AREASTRU ONH = {2,2,
			{-1.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,70.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{0.0,50.0,0.6},{0.0,0.0,0.0},2};

static AREASTRU NHP = {2,2,
			{-1.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND2,RHBOND2,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{0.0,50.0,0.6},{0.0,0.0,0.0},3};

static AREASTRU NARYL = {5,3,
			{-1.0,-1.0,0.0},{0.0,0.0,0.0},
			0.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{20.0,60.0,1.0},{0.0,0.0,0.0},4};

static AREASTRU AMID1 = {5,3,
			{0.0,0.0,1.0},{0.0,0.0,0.0},
			0.0,35.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW1,RVDW1,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,55.0,1.0},{0.5,0.0,0.0},5};

static AREASTRU AMID2 = {5,3,
			{0.0,0.0,-1.0},{0.0,0.0,0.0},
			0.0,35.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW1,RVDW1,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,55.0,1.0},{0.5,0.0,0.0},6};

static AREASTRU NAMINO = {6,4,
			{-1.0,-1.0,-1.0},{0.0,0.0,0.0},
			0.0,40.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.0,0.0},{0.3,0.7},
			{20.0,60.0,1.0},{0.0,0.0,0.0},7};

static AREASTRU SPH1 = {3,1,
			{0.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW1,RVDW1,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{-1.0,-1.0},
			{0.0,360.0,0.0},{0.0,0.0,0.0},8};
static AREASTRU SPH2 = {3,1,
			{0.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW3,RVDW3,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{-1.0,-1.0},
			{0.0,360.0,0.0},{0.0,0.0,0.0},9};
static AREASTRU CH3_PHE = {3,1,
			{0.0,0.0,0.0},{0.0,0.0,0.0},
			0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW2,RVDW1,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,360.0,0.0},{0.0,0.0,0.0},10};
static AREASTRU PHC1 = {4,3,
			{0.0,0.0,1.0},{0.0,0.0,0.0},
			0.0,70.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW2,RVDW2,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,20.0,1.0},{0.5,0.0,0.0},11};
static AREASTRU PHC2 = {4,3,
			{0.0,0.0,-1.0},{0.0,0.0,0.0},
			0.0,70.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW2,RVDW2,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,20.0,1.0},{0.5,0.0,0.0},12};
static AREASTRU PHR = {4,3,
			{-1.0,-1.0,0.0},{0.0,0.0,0.0},
			0.0,60.0,0.0,0.0,0.0,0.0,0.0,0.0,
			RVDW2,RVDW2,{DELVDW,DELVDW},EVDW,
			{1.0,0.0},{0.6,1.0},
			{0.0,30.0,1.0},{0.0,0.0,0.0},13};
static AREASTRU OSP3 = {1,3,
			{1.0,0.0,0.0},{0.0,1.0,0.0},
			-80.0,80.0,80.0,150.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{0.0,40.0,0.6},{0.0,0.0,0.0},14};
static AREASTRU OSP2 = {1,3,
			{1.0,0.0,0.0},{0.0,1.0,0.0},
			-60.0,60.0,90.0,160.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{0.0,40.0,0.6},{0.0,0.0,0.0},15};
static AREASTRU COC = {7,3,
			{1.0,-1.0,0.0},{1.0,1.0,0.0},
			-80.0,80.0,55.0,125.0,0.0,0.0,0.0,0.0,
			RHBOND1,RHBOND1,{DELHBOND,DELHBOND},EHBOND,
			{1.766,-0.15},{0.3,0.7},
			{75.0,140.0,0.0},{0.0,0.0,0.0},16};

#define H_ACC   0
#define H_DON   1
#define CH      2
#define CH2     3
#define CH3     4
#define PHE_CH3 5
#define ARO     6
#define AMIDE   7
#define SULFUR  8
#define PHENYL_CENTER  9
#define PHENYL_RING   10
#define METAL  11
#define METAL_ACC     12

static char *types[] = {"H_ACC","H_DON","CH","CH2","CH3","PHE_CH3","ARO",
			"AMIDE","SULFUR","PHENYL_CENTER","PHENYL_RING",
			"METAL","METAL_ACC"};
// INCRSTRUC explanation:
//
// type: above are the possible values of the 'type' element defined
//
// area: area is the interaction geometry for the interaction
//
// npts: npts is the number of points in the interaction surface array
// points: pointer to the interaction surface array
//
// n = the number of atoms defining this interaction point
// atom[0-3] is the atoms index in the cooordinate array
// c[0-3][3] are the atoms coordinates
//
// for a ligand interaction point these are all defined by a call
// to AllInt()
// for a protein interaction point only the atom coordinates c[0-3][3] are set
// since the rest can be derived through the type element
//
// nfrag: the member 'n' determines the number of atoms thats is used to
//        define the interaction geometry. From this FrgInt() determines
//        the number of different fragments these atoms belong to (nfrag)
//
// frag[0-3]: the fragment index for the max 4 number of fragments
//
// For OH ligands three rotamers are created. They all have the same
// absolute value of ohsame
//
// OH groups have an ACCeptor and a DONor. If they belong to the same OH group
// the link value is the same

#define MXCONFARR 2000

typedef struct {
		int type;
		AREASTRU area;
		int ohlig;
		int ohsame;
		double ORI[3];
		double c[4][3];
		double q0;
		double q1;
		double q2;
		double q3;
		double dih;
		int frag[4];
		int nfrag;
		int atom[4];
		int n;
		int npts;
		int link;
		int conf;
		int nconf;
		int *ConfArr;
		int res;
		int ires;
		double *points;
		} INCRSTRU;

static INCRSTRU *inttyp[20000];
#define MAXLIGSTRU 3500000
static INCRSTRU *ligtyp[MAXLIGSTRU];
static INCRSTRU IncrIni;

static double Tsin[361],Tcos[361];

void SetupTable()
{
  int alpha;

  for ( alpha=0; alpha < 361; alpha++ ) {
        Tsin[alpha] = sin((PI*alpha)/180.0);
        Tcos[alpha] = cos((PI*alpha)/180.0);
  }
}

void cpstr(ostr,str,nlen)
char *ostr;
char *str;
int nlen;
{
/* ostr (C) -> str (Fortran) */
  int i;
  int n;

  if (nlen) {
	n = MINI(strlen(ostr),nlen);
  } else {
	n = strlen(ostr);
  }

  for (i=0; i<nlen; i++) str[i] = '\0';
  strncpy(str,ostr,n);
}

void strcp(str,ostr,nlen)
char *str;
char *ostr;
int nlen;
{
/* str (fortran) -> ostr (C) */
  int i;

  for (i=0; i<nlen; i++) ostr[i] = '\0';
  strncpy(ostr,str,nlen);
}

static int Nlin;

void filmem(int iopt,int list,char *strn,FILEOP *fileop)
{
   FILE *f;
   struct stat buf;
   int i,n,fd,size,nlines,nfiles,ifiles,ilin;
   int ic = 0;
   size_t nl;
   int *linidx;
   int *fpos;
   char *string, *tstr, *tstrb;
   char maxlin[MAXCMD] = " ";

   fileop->list = list;
   fileop->opt = iopt;

   f = fopen(strn, "r");

   if (f != NULL) {

	rewind(f);
	fd = fileno(f);
	fstat(fd, &buf);
	size = buf.st_size;

	string = malloc(sizeof(char)*size+1);
	nl = fread(string, sizeof(char), size, f);
	if (nl == 0) {
	   fprintf(stderr,"Error reading file: %s\n", strn);
	   fileop->str = NULL;
	   fileop->size = 0;
	   string = NULL;
	   return;
	} else {
	   string[nl] = '\0';
	}
	fclose(f);

	fileop->str = string;
	fileop->size = nl;
   } else {
	fileop->str = NULL;
	fileop->size = 0;
	string = NULL;
   }

   if (!list) {
      if (COO[istruct] != NULL) {
	COO[istruct]->ihasmf = 1;
      }
   }

   tstr = string;
   
   nlines = 0;
   if (tstr != NULL) {
	while (*tstr != '\0') {
	   if (*tstr == '\n')  nlines++;
	   tstr++;
	}
   }

   fileop->nlines = nlines;

   fileop->fpos = NULL;

   if (iopt) {

	tstr = string;
	tstrb = tstr;
	nfiles = 0;

	while (!(*tstr == '\0' || ic == nl)) {
	   if (*tstr == '\n') {
		ic++;
        	n = (int) (tstr - tstrb);
		strncpy(maxlin,tstrb,n);
		tstrb = tstr;
		tstr++;
		if (strstr(maxlin,"$$$$") != NULL) nfiles++;
		if (strstr(maxlin,"<TRIPOS>MOLECULE") != NULL) nfiles++;
	   } else {
		tstr++;ic++;
	   }
	}

	fileop->nfiles = nfiles;

	fileop->fpos = malloc(sizeof(int)*(nfiles+2));

	if (fileop->fpos != NULL) {
	   fileop->fpos[0] = 0;
	   tstr = string;
	   tstrb = tstr;
	   if (strstr(strn,".sdf")) {
	      ifiles = 0;
	   } else if (strstr(strn,".mol2")) {
	      ifiles = -1;
	   }

	   while (*tstr != '\0') {
		if (*tstr == '\n') {
        	   n = (int) (tstr - tstrb);
		   strncpy(maxlin,tstrb,n);
		   tstr++;
		   if (strstr(maxlin,"$$$$") != NULL) {
			ifiles++;
			fileop->fpos[ifiles] = (int) (tstr - string);
		   }
		   if (strstr(maxlin,"<TRIPOS>MOLECULE") != NULL) {
			ifiles++;
			if (ifiles == 0) {
			   fileop->fpos[0] = 0;
			} else {
			   fileop->fpos[ifiles] = (int) (tstrb - string);
			}
		   }
		   tstrb = tstr;
	   	} else {
		   tstr++;
	   	}
	   }
	}

	if (nfiles > mfdata->maxmol) {
	   if (mfdata->mollin != NULL) safefree((void **)&mfdata->mollin);
	   mfdata->mollin = (int *) malloc(sizeof(int)*(nfiles+2));
	   mfdata->mollin[0] = 0;
	   mfdata->maxmol = nfiles;
	   if (mlftit != NULL) safefree((void **)&mlftit);
	   mlftit = (char **) malloc(sizeof(char *)*(nfiles+2));
	   mxtits = nfiles;
	}
   }

   Nlin = nlines+1;
   linidx = malloc(sizeof(int)*(nlines+1));
   fileop->line_index = linidx;

   if (list) {
	fileop->lines = malloc(sizeof(char *)*(nlines+1));
   }

   ilin = 1;
   tstr = string;
   linidx[0] = 0;
   if (tstr != NULL) {
     while (*tstr != '\0') {
	int i1,i2,n;
	if (*tstr == '\n') {
	   linidx[ilin] = (int) (tstr - string + 1);
	   if (list) {
		i2 = linidx[ilin];
		if (ilin == 1) {
		   i1 = 0;
		} else {
		   i1 = linidx[ilin-1];
		}
	   	n  = i2 - i1 - 1;
		fileop->lines[ilin-1] = malloc(sizeof(char)*(n+1));
		strncpy(fileop->lines[ilin-1],&string[i1],n);
		fileop->lines[ilin-1][n] = '\0';
	   }
	   ilin++;
	}
	tstr++; 
     }
   }

   if (!list) {
      if (COO[istruct] != NULL) {
	COO[istruct]->memfil = *fileop;
      }
   }
}

void connij_(idcon,i,j,idoconv)
int *idcon;
int *i;
int *j;
int *idoconv;
{

	connid_(idcon,i,j,idoconv,
		xyzp->iconn,xyzp->ianz,xyzp->coo);

}

void pdbtyp_(ipdb,ihpdb,jres,ihashy)
int *ipdb;
int *ihpdb;
int *jres;
int *ihashy;
{

	pdbtyd_(ipdb,ihpdb,jres,ihashy,xyzp->ipdbt);

}

void flagh_(ihpdb,iat)
int *ihpdb;
int *iat;
{

	flagd_(ihpdb,iat,xyzp->isurf);

}

void conat_(ipdb,iat1,iat2,iop)
int *ipdb;
int *iat1;
int *iat2;
int *iop;
{

	conad_(ipdb,iat1,iat2,iop,xyzp->iconn);

}

void conath_(ipdb,ihpdb,iat1,iat2)
int *ipdb;
int *ihpdb;
int *iat1;
int *iat2;
{

	conatd_(ipdb,ihpdb,iat1,iat2,xyzp->iconn);

}

void mkback_(ipdb,ihpdb,jres,icres,ihashy,idoconv)
int *ipdb;
int *ihpdb;
int *jres;
int *icres;
int *ihashy;
int *idoconv;
{

/*
 The variable NW_MKBACK switches betwwen the old (NW_MKBACK=0)
 and the new (NW_MKBACK=0) form of mkback. The old version depended
 on the next call (residue nr. one higher) to complete the connections of
 Coo. Hence if called on its own the Coo connections would not be complete.
 However since the icalf variables of the next residue have NOT been set
 at the time when it is first called, we still need this one !!!

 The new form of mkback can be called on its own and have all connections
 complete. Depend on icalf variables already been set for all residues.
*/

    if (NW_MKBACK) {
	mkbadd_(ipdb,ihpdb,jres,icres,ihashy,idoconv,
	xyzp->iconn,xyzp->coo,
        calfptr->icalf,calfptr->ianf,calfptr->islu,
        &calfptr->nchain,calfptr->iamino);
    } else {
	mkbacd_(ipdb,ihpdb,jres,icres,ihashy,idoconv,
	xyzp->iconn,xyzp->coo,
        calfptr->icalf,calfptr->ianf,calfptr->islu,
        &calfptr->nchain,calfptr->iamino);
    }

}

void mknbck_(ipdb,ihpdb,jres,icres,ihashy,idoconv)
int *ipdb;
int *ihpdb;
int *jres;
int *icres;
int *ihashy;
int *idoconv;
{

	mknbcd_(ipdb,ihpdb,jres,icres,ihashy,idoconv,
	xyzp->iconn,xyzp->coo,
        calfptr->icalf,calfptr->ianf,calfptr->islu,
        &calfptr->nchain,calfptr->iamino);

}

void numhet_(num)
int *num;
{

	numhed_(num,xyzp->iresid);

}

void prslab_(str, nstr, iopt)
char *str;
int *nstr;
int *iopt;
{

       if (hetlab.NHetLab >= MXHETLAB) return;
       
       hetlab.iat[hetlab.NHetLab]    = *iopt;

       hetlab.HetLab[hetlab.NHetLab] = (char *) malloc(*nstr+1);

       if (!hetlab.HetLab[hetlab.NHetLab]) 
		fprintf(stderr,"prslab: malloc error\n");

       strcp(str,hetlab.HetLab[hetlab.NHetLab],*nstr);

       hetlab.HetLab[hetlab.NHetLab][*nstr] = '\0';
       hetlab.NHetLab++;

}

void chkmol2_(iok)
int *iok;
{
   chkmld_(iok,xyzp->ianz,xyzp->ityp);

}

void ispn_(ispn,iat,irng,idochg,ifive)
int *ispn;
int *iat;
int *irng;
int *idochg;
int *ifive;
{
*ispn = 0;
	ispnd_(ispn,iat,irng,idochg,ifive,
	xyzp->qat,xyzp->ianz,xyzp->iaton,xyzp->iconn,xyzp->lwrit,xyzp->lring);

}

void bckfil_()
{

 if (COO[istruct] == NULL || nomemf) {
    bcfile_();
    return;
 }

 if (COO[istruct]->memfil.str != NULL) {

    COO[istruct]->memfil.currl--;
    if (COO[istruct]->memfil.currl < 0) COO[istruct]->memfil.currl = 0;
 } else {

    bcfile_();

 }
}

void fnormalize(v)     
float *v;
{
   float d;

   d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); 

   if (d != 0.0) {

	v[0] /= d; v[1] /= d; v[2] /= d; 

   }
}

void nxtlin_(str,istat)
char *str;
int *istat;
{
   int i1,i2;
   int i,n;
   char *t;

   if (COO[istruct] == NULL || nomemf) {
	nxline_(str,istat);
	return;
   }

   if (COO[istruct]->memfil.str != NULL) {

	*istat = 0;
	i1 = COO[istruct]->memfil.line_index[COO[istruct]->memfil.currl];
	COO[istruct]->memfil.currl++;

	if (COO[istruct]->memfil.currl < COO[istruct]->memfil.nlines) {
	   i2 = COO[istruct]->memfil.line_index[COO[istruct]->memfil.currl];
	   n = i2 - i1 - 1;
	} else {
	   if (COO[istruct]->memfil.currl == COO[istruct]->memfil.nlines) {
		n = COO[istruct]->memfil.size - i1 - 1;
	   } else {
		COO[istruct]->memfil.currl = COO[istruct]->memfil.nlines - 1;
		*istat = 1;
		return;
	   }
	}

	if (n > MXSTRFOR) n = MXSTRFOR;
	if (n < 0) n = 0;

	strncpy(str,&COO[istruct]->memfil.str[i1],(size_t) n);
	str[n] = '\0';
	for (i=n+1; i<MXSTRFOR; i++) str[i] = ' ';

   } else {
   
	nxline_(str,istat);

   }

}

void redel_(str,n)
char *str;
int *n;
{
    int i;
    int istat;

   if (COO[istruct] == NULL || nomemf) {
    readel_(str,n);
    return;
   }

   if (COO[istruct]->memfil.str != NULL) {
    for (i=0; i<*n; i++) {
	nxtlin_(str,&istat);
    }
   } else {

    readel_(str,n);

   }
}

void rewmf_()
{
    rewmd_(mfdata->mollin);
}

void rewfil_()
{

 if (COO[istruct] == NULL || nomemf) {
    rwfile_();
    return;
 }

 if (COO[istruct]->memfil.str != NULL) {
   COO[istruct]->memfil.currl = 0;
 } else {

    rwfile_();

 }
}

void setiat(int iatoms)
{
   setatms_(&iatoms);
}

void Get_Tsin(int dg, double *sina, double *cosa)
{
   int deg;

   if (dg >= 0) {
	*sina = Tsin[dg]; *cosa = Tcos[dg];
   } else {
        deg = dg + 360;
	*sina = Tsin[deg]; *cosa = Tcos[deg];
   }
}
   
void Get_FTsin(int dg, float *sina, float *cosa)
{
   int deg;

   if (dg >= 0) {
	*sina = (float) Tsin[dg]; *cosa = (float) Tcos[dg];
   } else {
        deg = dg + 360;
	*sina = (float) Tsin[deg]; *cosa = (float) Tcos[deg];
   }
}
   
void crossprd(v1,v2,d)
double *v1;
double *v2;
double *d;
{
/*

       calculates cross product:  (v1) x (v2) = d
                                   ---     ---    -
*/
      int i;
      double dlen;

      d[0] = v2[1]*v1[2]-v2[2]*v1[1];
      d[1] = v2[2]*v1[0]-v2[0]*v1[2];
      d[2] = v2[0]*v1[1]-v2[1]*v1[0];
      dlen = sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);

      if (dlen > 0 ) for (i=0; i<3; i++) d[i] = d[i] / dlen;
}

float veclen(float *a)
{
      float vl;
      double tot;

      tot = a[0]*a[0]+a[1]*a[1]+a[2]*a[2];

      vl = 0.0;
      if (tot > 0.0) vl = (float) sqrt(tot);

      return(vl);

}

double dveclen(double *a)
{
      double vl;
      double tot;

      tot = a[0]*a[0]+a[1]*a[1]+a[2]*a[2];

      vl = 0.0;
      if (tot > 0.0) vl = (double) sqrt(tot);

      return(vl);

}

void vecnrm(float *v)
{
   float vl;
   int j;

   vl = veclen(v);
   if (vl != 0.0) {
      for (j=0; j<3; j++) {
	v[j] = v[j] / vl;
      }
   }
}

void cross(float *a,float *b, float *c)
{
/*

       calculates cross product:   a x b = c
                                   -   -   -
*/
 
      c[0] = a[1]*b[2] - a[2]*b[1];
      c[1] = a[2]*b[0] - a[0]*b[2];
      c[2] = a[0]*b[1] - a[1]*b[0];

}

void dinprod(double *a, double *b, double *c)
{
      int i;
      double rimp, al, bl;

      rimp = 0.0;

      for (i=0; i<3; i++) rimp = rimp + a[i]*b[i];

      al = dveclen(a);
      bl = dveclen(b);

      if (al > 0.0 && bl > 0.0) {
         *c = rimp / (al*bl);
      } else {
         *c = 0.0;
      }

}

void inprod(float *a, float *b, double *c)
{
      int i;
      float rimp, al, bl;

      rimp = 0.0;

      for (i=0; i<3; i++) rimp = rimp + a[i]*b[i];

      al = veclen(a);
      bl = veclen(b);

      if (al > 0.0 && bl > 0.0) {
         *c = (double) rimp / (veclen(a)*veclen(b));
      } else {
         *c = 0.0;
      }

}

void IMPRD(float *a, float *b, float *c,int norm)
{
      int i;
      float rimp, al, bl;

      rimp = 0.0;

      for (i=0; i<3; i++) rimp = rimp + a[i]*b[i];

      al = veclen(a);
      bl = veclen(b);

      if (al > 0.0 && bl > 0.0) {
	 if (norm) {
            *c = rimp / (veclen(a)*veclen(b));
	 } else {
            *c = rimp;
	 }
      } else {
         *c = 0.0;
      }

}

void vsubt(float *a, float *b, float *c)
{
      int i;

      for (i=0; i<3; i++) c[i] = a[i] - b[i];
}

void vsubd(double *a, double *b, double *c)
{
      int i;

      for (i=0; i<3; i++) c[i] = a[i] - b[i];
}

static SNGSTRU singleb;

void parptr_(nptr, fptr, ffptr, nitem)

int *nptr;
float *fptr;
float *ffptr;
int *nitem;
{
    switch(*nptr) {
    case 0: dcksol = *nitem;
            break;
    case 1: LigSel = *nitem;
	    LigSel = LigSel + 5;
            break;
    case 2: debugdck = *nitem;
            break;
    case 3: FASTSLOW = *nitem;
            break;
    case 4: switch(*nitem) {
		case 0: DCKdev = 0.65;
			break;
		case 1: DCKdev = 1.00;
			break;
		case 2: DCKdev = 1.50;
			break;
		case 3: DCKdev = 2.00;
			break;
	    }
            break;
    case 6: fniun = (FNIUNSTRU *) nitem; 
            break;
    case 7: atomptr = (ATOMSTRU *) fptr; 
	    xyz.coo = (double *) atomptr->coo;
	    xyz.rzp = (double *) atomptr->rzp;
	    xyz.ianz = (int *) atomptr->ianz;
	    xyz.iaton = (int *) atomptr->iaton;
	    xyz.iatclr = (int *) atomptr->iatclr;
	    xyz.iresid = (int *) atomptr->iresid;
	    xyz.ixp = (int *) atomptr->ixp;
	    xyz.iyp = (int *) atomptr->iyp;
	    xyz.iconn = (int *) atomptr->iconn;
	    xyz.icont = (int *) atomptr->icont;
	    break;
    case 8: elmptr = (ELMSTRU *) fptr; break;
    case 15: xyz.iatoms = nitem;
	     xyz.mxorg = 0;
	     break;
    case 41: jring = nitem; break;
    case 47: xyz.qat = (double *) fptr; 
	     break;
    case 48: fftyp = nitem; break;
    case 49: xyz.ityp = (int *) nitem; 
	     break;
    case 50: xyz.ipdbt = (int *) nitem; 
	     break;
    case 51: calfptr = (CALFSTRU *) nitem; break;
    case 65: ipdbon = nitem; break;
    case 142: XYZ = (XYZSTRU *) fptr; break;
    case 149: xyz.isurf = nitem; break;
    case 158: xyz.mxnat = nitem; break;
    case 159: xyz.lwrit = nitem; break;
    case 160: xyz.lring = nitem; break;
    case 161: xyz.inat = nitem; break;

    case 181: mfdata = (MFSTRU *) nitem; 
	      mfdata->mollin = (int *) malloc(sizeof(int)*MXMFMOL);
	      mfdata->mollin[0] = 0;
	      mfdata->maxmol = MXMFMOL;
	      mlftit = (char **) malloc(sizeof(char *)*MXMFMOL);
	      mxtits = MXMFMOL;
              break;
    case 191: clfstrptr = (CLFSTRU *) nitem; break;
    case 208: mets = (METSTRU *) fptr; break;
    case 209: eneptr = (ENERSTRU *) nitem; break;
    case 210: chgvdwptr = (CHGVDWSTRU *) fptr; break;
    }
}

void parsfn_(str, nstr, iopt)

char *str;
int *nstr;
int *iopt;
{
       int j;
       char **strarr;
       int *nstrings;
       int room;
       char tmpstr[MAXPATHLEN];

       switch(*iopt) {
       case 0:
          strarr = &pdbfil;
          j = 0;
          nstrings = &j;
          room = *nstr + 1;
          break;
       case 1: 
	  strarr = hetptr.HetAtm;
	  nstrings = &hetptr.NHetAtm;
	  if (hetptr.NHetAtm >= MXHETA) return;
	  hetptr.Allocated[*nstrings] = 1;
	  room = *nstr + 1;
	  break;
       case 2: 
	  strarr = &dcklig;
	  j = 0;
          nstrings = &j;
	  room = *nstr + 1;
	  break;
       case 4: 
	  strarr = &site;
	  j = 0;
          nstrings = &j;
	  room = *nstr + 1;
	  break;
       case 6: 
	  strarr = mol2;
	  nstrings = &Nmol2;
	  room = *nstr + 1;
	  break;
       case 8: 
	  strarr = ambstr;
	  nstrings = &Nambstr;
	  room = *nstr + 1;
	  break;
       case 11: 
	  strarr = achain;
	  nstrings = &ncal;
	  room = *nstr + 1;
	  break;
       case 13: 
	  strarr = mlftit;
	  nstrings = &ntits;
	  room = *nstr + 1;
	  if (ntits >= mxtits) return;
	  break;
       case 19: 
	  strarr = gffext;
	  nstrings = &Ngffext;
	  room = *nstr + 1;
	  break;
       case 20: 
	  strarr = exepath;
	  nstrings = &Nexepath;
	  room = *nstr + 1;
       }

       strarr[*nstrings] = (char *) malloc(room);
       if (!strarr[*nstrings]) fprintf(stderr,"getfiles: malloc error\n");
       strcp(str,strarr[*nstrings],*nstr);
       strarr[*nstrings][*nstr] = '\0';
       (*nstrings)++;

       if (*iopt == 20) {
	  char *p;
	  
	  if ((p = strrchr(exepath[0], '/'))) {
		p++; *p = '\0';
	  } else {
		p = exepath[0];
		*p = '\0';
	  }

	  realpath(exepath[0],molden_root);
	  if (strstr(molden_root,"bin")) {
		strncpy(molden_rootb,molden_root,strlen(molden_root)-4);
	  } else {
		strcpy(molden_rootb,molden_root);
	  }
	  molden_rootb[strlen(molden_root)] = '\0';
	  strcpy(molden_root,molden_rootb);
	  if ((p = strrchr(molden_root, ' '))) *p = '\0';
	  sprintf(home_dir,"%s",getenv("HOME"));

	  sprintf(tmpstr,"%s/tmp/",molden_root);

	  if (access(tmpstr,X_OK) == 0) {
		tmpon = 1;
		cpstr(tmpstr,mldfile,MAXCMD5);
	  } else {
		mkdir(tmpstr,0777);
		tmpon = 1;
		cpstr(tmpstr,mldfile,MAXCMD5);
	  }


       }

       if (*iopt == 2) {
	  strcpy(firstfile,dcklig);
       }

       if (*iopt == 4) {
	  strncpy(sitestr,site,3);
       }
}

int FndSite()
{
   int j;

   for (j=4; j<hetptr.NHetAtm; j++) {
	if (strcmp(hetptr.HetAtm[j],sitestr) == 0) {
	   return(j);
	}
   }
   return(-1);
}

void allcoo_(ZSizep,first)
int *ZSizep;
int *first;
{
   int memstat;
   double d;
   int i;
   int j;
   int ZSize;

   memstat = 1;
   if (*first) {
        if (*first == 1) {
	   ZSize = NUMAT;
	} else {
	   ZSize = *ZSizep;
	}
   } else {
	ZSize = *xyzp->mxnat + *ZSizep;
	TMPxyz = *xyzp;
   }

   if ((xyzp->coo = (double *) malloc((sizeof d)*ZSize*3)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->rzp = (double *) malloc((sizeof d)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->qat = (double *) malloc((sizeof d)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->isurf = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->icont = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->lwrit = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->lring = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->ianz = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iaton = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iatclr = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iresid = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->ixp = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iyp = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iconn = (int *) malloc((sizeof i)*ZSize*(MXCON+1))) == NULL) {
	memstat = 0;
   }

   if ((xyzp->inat = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->ityp = (int *) malloc((sizeof j)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->ipdbt = (int *) malloc((sizeof j)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzp->iclos = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if (!memstat) {
	fprintf(stderr,"Out of memory allcoo\n");
	if (!*first) *xyzp = TMPxyz;
   } else {
	if (*first) {
	   xyzp->iatoms = xyz.iatoms;
	   xyzp->ncont = xyz.ncont;
	   xyzp->mxnat = xyz.mxnat;
	   for (i=0; i < ZSize; i++) {
		xyzp->qat[i] = 0.0;
		xyzp->ianz[i] = 0;
		xyzp->ityp[i] = 0;
		xyzp->iaton[i] = 0;
		xyzp->iatclr[i] = 1;
		xyzp->iresid[i] = 0;
		xyzp->ipdbt[i] = 0;
		xyzp->lring[i] = 0;
	   }
	} else {
	   for (i=0; i < *xyzp->iatoms; i++) {
	   	for (j=0; j<3; j++) xyzp->coo[i*3+j] = TMPxyz.coo[i*3+j];
		xyzp->qat[i] = TMPxyz.qat[i];
		xyzp->ianz[i] = TMPxyz.ianz[i];
		xyzp->iaton[i] = TMPxyz.iaton[i];
		xyzp->iatclr[i] = TMPxyz.iatclr[i];
		xyzp->iresid[i] = TMPxyz.iresid[i];
		xyzp->ityp[i] = TMPxyz.ityp[i];
		xyzp->ipdbt[i] = TMPxyz.ipdbt[i];
		xyzp->lring[i] = TMPxyz.lring[i];
		xyzp->isurf[i] = TMPxyz.isurf[i];
		for (j=0; j<MXCON; j++)
		   xyzp->iconn[i*(MXCON+1)+j] = TMPxyz.iconn[i*(MXCON+1)+j];
	   }
	}
	xyzp->mxorg = 1;
	*(xyzp->mxnat) = ZSize;
   }
}

int allConf(xyzc,ZSize)
double **xyzc;
int ZSize;
{
   int memstat;
   double d;

   memstat = 1;

   if ((*xyzc = (double *) malloc((sizeof d)*ZSize*3)) == NULL) {
	memstat = 0;
   }

   if (!memstat) {
	fprintf(stderr,"Out of memory AllConf\n");
	return(0);
   }

   return(1);
}

int allFConf(xyzc,ZSize)
float **xyzc;
int ZSize;
{
   int memstat;
   float f;

   memstat = 1;

   if ((*xyzc = (float *) malloc((sizeof f)*ZSize*3)) == NULL) {
	memstat = 0;
   }

   if (!memstat) {
	fprintf(stderr,"Out of memory AllFConf\n");
	return(0);
   }

   return(1);
}

/*
- HEM:
  CAC 1*H (HAC) is added
  CAB 1*H (HAB) is added
  O2A 1*H (H2A) we choose NOT to add it
  O2B 1*H (H2B) we choose NOT to add it

  Discription HEM should include 2H's for CAB,CAC. It does not, This means
  the connections with amino acids are taken into account.

  discription HEM includes Fe (probably Fe2+, offsets 2*COO- charges:
  total Neutral, which is the initial formal charge given. But
  actually it should be 2+, because the description uses 2*COOH).

  Message 1: do NOT subtract because of connections with amino acids.
  Message 2: exclude FE from partial charge calculation, and set q(FE)=+2
*/

int isPO4(iat)
int iat;
{
    int xc,io,icns,k,l,la;

    if (xyzp->ianz[iat] != 15) return 0;
    xc = xyzp->iconn[iat*(MXCON+1)];

    io = 0;
    icns = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8) io++;
	   if (xyzp->ianz[la-1] == 6 || xyzp->ianz[la-1] == 7 || xyzp->ianz[la-1] >= 16) icns++;
	}
    }

    if (io == 4 || (io+icns == 4 && io >= 2) ) return 1;
    return 0;
}

int isCOO(iat)
int iat;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (xyzp->ianz[iat] != 6) return 0;

    io = 0;
    ic = 0;
    ih = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8) io++;
	   if (xyzp->ianz[la-1] == 6) ic++;
	   if (xyzp->ianz[la-1] == 1) ih++;
	}
    }

    if (io == 2 && ic == 1 && ih == 0) return 1;
    return 0;
}

int isBH4(iat)
int iat;
{
    int xc,io,ic,is,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (xyzp->ianz[iat] != 5) return 0;

    io = 0;
    ic = 0;
    is = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8) io++;
	   if (xyzp->ianz[la-1] == 6) ic++;
	   if (xyzp->ianz[la-1] == 16) is++;
	}
    }

    if (io + ic + is == 4) return 1;
    return 0;
}

int TertN(iat,con)
int iat;
int *con;
{
    int xc,i,io,ic,ich,ir,k,l,la,iout,iat1;

    ic = 0; ich = 0;
    xc = xyzp->iconn[iat*(MXCON+1)];
    ir = xyzp->iresid[iat];
    iat1 = iat + 1;
    iout = 0;
    
    getrng_(&iat1,&iout,xyzp->ianz,xyzp->iconn);

    if (iout) return 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 6) {
		if (ic < 3) con[ic] = la;
		ic++;
	   }
	   if (xyzp->ianz[la-1] == 1) ich++;
	}
    }
    if (ic == 3 && ! (ich == 1)) return 1;
    return 0;
}

int isit_metal(ian)
int ian;
{
  int k;

  for (k=0; k < MEXCL; k++) {
	if (ian == mets->ianexc[k]) return 1;
  }

  return 0;
}
 
static int nintp = 0;
static int lintp = 0;
static int lintconf = 0;
static int lind[MAXLIGSTRU];
static float Eself = 0.0;
void cal_area(INCRSTRU *i);

typedef struct {
		float d;
		uint16_t grp1;
		uint16_t ind1;
		uint16_t pnt1;
		uint16_t grp2;
		uint16_t ind2;
		uint16_t pnt2;
		} CROSSSTRU;

typedef struct {
		int ind;
		int n;
		} HASHSTRU;

typedef struct {
		CROSSSTRU *XDist;
		int l;
		HASHSTRU *XHash;
		int n;
		} GRPSTRU;

#define MAXTRI 400000
#define MAXSTRI 50000
#define MAXCHK 5
#define CLOSEC 0.4
#define CLUSRMS  0.1
#define CLUSRMS2 0.05
static float VDWSCAL = 0.1;
#define MAXSOL  25
#define PRECISE 0

static float vdwscal = 1.0;
static float vdwscal_memory = 1.0;


typedef struct {
		float d12;
		float d13;
		float d23;
		float p1[3];
		float p2[3];
		float p3[3];
		int lig[3];
		int ohlig[3];
		int grp[3];
		int atindx[3];
		int frag;
		int frags[3];
		int conf;
		int nconf;
		int *ConfArr;
		int active;
		int oneline;
		} TRISSTRU;

static TRISSTRU TriS[MAXSTRI];

static int ntriS = -1;

// p1c,p2c,p3c contains translated and rotated ligand interaction point 
// coordinates

// P1,P2,P3 contains original untranslated and unrotated ligand interaction 
// point coordinates

// v[3] is the rotation axis vector, when spec element is set to one

// the spec element of TRISTRU determines if there is a special case
// of one ACC/DON PAIR (spec == 1)

static int HAS_SPEC = 0;
static int EXTRA_IP = 0;

typedef struct {
		float d12;
		float d13;
		float d23;
		float p1[3];
		float p2[3];
		float p3[3];
		float v[3];
		int lig[3];
		int ohlig[3];
		int prot[3];
		float p1c[3];
		float p2c[3];
		float p3c[3];
		float P1[3];
		float P2[3];
		float P3[3];
		float Cen[3];
		float Out[3];
		float CenO[3];
		float OutO[3];
		float OutOrg[3];
		float e12;
		float e12c[3];
		float eint;
		float etot;
		float overl;
		float dcnt;
		int frag;
		int frags[3];
		int grp[3];
		int idx[3];
		int triS;
		int conf;
		int nconf;
		int spec;
		int small;
		int done;
		int dorot;
		int itry;
		int oneline;
		double *coo;
		double *oh[3];
		double t[3];
		double R1[4][4];
		double R2[4][4];
		double R3[4][4];
		} TRISTRU;

typedef struct {
		int lig[3];
		int prot[3];
		int imin;
		float esum;
		float emin;
		float emin2;
		int nentries;
		} LIGSTRU;

typedef struct {
		double *coo;
		} CARSTRU;

static TRISTRU Tri1;
static TRISTRU Tri2;
static TRISTRU Tri3;
static TRISTRU *TriArr[MAXTRI] = {NULL};
static TRISTRU *TriFin[MAXSTRI];
static TRISTRU *TriArrCopy[MAXTRI];
static TRISTRU *TriCHK[MAXCHK];
static CARSTRU *TriC[MAXTRI];
static TRISTRU TriIni;
static int ntris = -1;
static int ntrif = -1;
static int nchk = -1;

typedef struct {
		int i;
		int j;
		double dd;
		int stat;
		int *Arr;
		int N;
		} LDAT;

typedef struct {
		int Num;
		int *Arr;
		int N;
		int CC;
		} NNODE;

typedef struct node
{
    struct node *prev_node;
    LDAT info;
    struct node *next_node;
} node;
 
node *begin=NULL;

void xyzROT4(double R[4][4],float *vt);
void RemCC_One(int L);
void Trans_Trans(TRISTRU *Tri,double *coo);
void Frst_Rot(float *cc,float *uu,double sina,double cosa,double R[4][4]);
void Trans_Tri(TRISTRU *Tri1,TRISTRU *Tri2,int opt);
void Calc_Centroid(TRISTRU *Tri);
float CalInt(int ind1,int ind2,double *points,double t[3],double R1[4][4],double R2[4][4],float *OutO, float *OutOrg, int deb);
float CalInt_Spec(int ind1,int ind2,double *points,double t[3],double R1[4][4],double R2[4][4],float *OutO, float *OutOrg, int spec, int deb);
void dsply_List(node *begin);
void set_List(node *begin,node **barr,int *N,int MXARR);
void replc_List(node *begin,int val,int nval);
void upd_List(node **barr,int *N,node *delnode);
struct node *addtoemptylist(node *begin,LDAT data_element);
struct node *addatendlist(node *begin,LDAT data_element);
struct node *insertdd(node *begin,node **barr,int *N,LDAT data_element);
struct node *deletenode(node *begin,node *delnode,LDAT *data_element,node **barr,int *N);
struct node *dlnode(node *begin,LDAT *data_element);

/* group R and RH */
static int GrpR[6] = {6,8,7,16,15,9};
static int GrpRH[] = {6,8,7,16,15,9,1};

static int Cany[] = {7,6,5,8};
static int C2ar[] = {8,6};
static int Nany[] = {12,11,10,13,14,15,16};
static int N2ar[] = {11,13};
static int Nplan[] = {14,15};
static int Oany[] = {18,17,19};
static int Odbl[] = {18,19};
static int Sany[] = {23,22,24,25};
static int Aany[] = {11,13,15,6,8,23};
static int DONG[] = {18,17,12,11,10,13,14,15,16};

static int isq[6][3] = { 0,1,3, 0,3,1, 1,0,3, 3,0,1, 1,3,0, 3,1,0};

static float gfvdw[MXGFF][2] = {
     {   0.0000, 0.0000},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.1094},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.9080, 0.0860},
     {   1.3870, 0.0157},
     {   1.2870, 0.0157},
     {   1.1870, 0.0157},
     {   1.4090, 0.0150},
     {   1.3590, 0.0150},
     {   1.4590, 0.0150},
     {   1.4870, 0.0157},
     {   0.6000, 0.0157},
     {   0.0000, 0.0000},
     {   0.6000, 0.0157},
     {   0.6000, 0.0157},
     {   0.0000, 0.0000},
     {   1.1000, 0.0157},
     {   1.75  , 0.061 },
     {   1.948 , 0.265 },
     {   2.22  , 0.320 },
     {   2.35  , 0.40  },
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.8240, 0.1700},
     {   1.6612, 0.2100},
     {   1.7210, 0.2104},
     {   1.6837, 0.1700},
     {   1.7683, 0.1520},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.1000, 0.2000},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   2.0000, 0.2500},
     {   1.9080, 0.0860} 
};

#define MXGTOR 638
#define MXTORS 4*NUMATM 

static int gftcon[MXGTOR][4] = {
     { 1, 2, 2, 1},
     { 1, 2, 3, 1},
     { 1, 2,13, 1},
     { 1, 2,14, 1},
     { 1, 2, 4, 1},
     { 1, 2,17, 1},
     { 1, 2,18, 1},
     { 1, 2,11, 1},
     { 1, 2,12, 1},
     { 1, 2, 5, 1},
     { 1, 2,15, 1},
     { 1, 2,16, 1},
     { 1, 2, 6, 1},
     { 1, 2, 9, 1},
     { 1, 2,10, 1},
     { 1, 2,36, 1},
     { 1, 2,38, 1},
     { 1, 2,43, 1},
     { 1, 2,44, 1},
     { 1, 2,45, 1},
     { 1, 2,46, 1},
     { 1, 2,41, 1},
     { 1, 2,48, 1},
     { 1, 2,50, 1},
     { 1, 2,51, 1},
     { 1, 2,58, 1},
     { 1, 2,53, 1},
     { 1, 2,58, 1},
     { 1, 2,59, 1},
     { 1, 2,60, 1},
     { 1, 2,61, 1},
     { 1, 2,54, 1},
     { 1, 2,55, 1},
     { 1, 2,62, 1},
     { 1, 2,56, 1},
     { 1, 2,63, 1},
     { 1, 2,68, 1},
     { 1, 2,69, 1},
     { 1, 2,66, 1},
     { 1, 2,70, 1},
     { 1, 2,67, 1},
     { 1, 2,71, 1},
     { 1, 3, 3, 1},
     { 1, 3,13, 1},
     { 1, 3,14, 1},
     { 1,13,13, 1},
     { 1,14,14, 1},
     { 1,13,14, 1},
     { 1, 3, 4, 1},
     { 1, 3, 5, 1},
     { 1, 3, 6, 1},
     { 1, 3, 9, 1},
     { 1, 3,10, 1},
     { 1, 3,11, 1},
     { 1, 3,12, 1},
     { 1, 3,17, 1},
     { 1, 3,18, 1},
     { 1, 3,15, 1},
     { 1, 3,16, 1},
     { 1, 3,36, 1},
     { 1, 3,38, 1},
     { 1, 3,39, 1},
     { 1, 3,40, 1},
     { 1, 3,41, 1},
     { 1, 3,42, 1},
     { 1, 3,43, 1},
     { 1, 3,44, 1},
     { 1, 3,45, 1},
     { 1, 3,46, 1},
     { 1, 3,47, 1},
     { 1, 3,48, 1},
     { 1, 3,50, 1},
     { 1, 3,51, 1},
     { 1, 3,53, 1},
     { 1, 3,57, 1},
     { 1, 3,58, 1},
     { 1, 3,59, 1},
     { 1, 3,60, 1},
     { 1, 3,61, 1},
     { 1, 3,54, 1},
     { 1, 3,55, 1},
     { 1, 3,62, 1},
     { 1, 3,56, 1},
     { 1, 3,63, 1},
     { 1, 3,65, 1},
     { 1, 3,68, 1},
     { 1, 3,69, 1},
     { 1, 3,66, 1},
     { 1, 3,70, 1},
     { 1, 3,67, 1},
     { 1, 3,71, 1},
     { 1, 4, 4, 1},
     { 1, 4,11, 1},
     { 1, 4,12, 1},
     { 1,11,12, 1},
     { 1,11,11, 1},
     { 1,12,12, 1},
     { 1, 9,10, 1},
     { 1, 9, 9, 1},
     { 1,10,10, 1},
     { 1, 4, 5, 1},
     { 1, 4, 6, 1},
     { 1, 4,36, 1},
     { 1, 4,38, 1},
     { 1, 4,45, 1},
     { 1, 4,46, 1},
     { 1,11,45, 1},
     { 1,12,46, 1},
     { 1, 4,43, 1},
     { 1, 4,44, 1},
     { 1, 9,44, 1},
     { 1,10,43, 1},
     { 1, 9,43, 1},
     { 1,10,44, 1},
     { 1, 4,39, 1},
     { 1, 4,40, 1},
     { 1, 4,41, 1},
     { 1, 9,41, 1},
     { 1,10,41, 1},
     { 1, 4,47, 1},
     { 1, 4,48, 1},
     { 1, 4,50, 1},
     { 1, 4,51, 1},
     { 1, 4,53, 1},
     { 1, 4,60, 1},
     { 1, 4,61, 1},
     { 1,11,61, 1},
     { 1,11,60, 1},
     { 1,12,61, 1},
     { 1, 4,58, 1},
     { 1, 4,59, 1},
     { 1, 9,58, 1},
     { 1, 9,59, 1},
     { 1,10,58, 1},
     { 1,10,59, 1},
     { 1, 4,54, 1},
     { 1, 4,55, 1},
     { 1,11,55, 1},
     { 1,12,55, 1},
     { 1, 4,62, 1},
     { 1,11,62, 1},
     { 1,12,62, 1},
     { 1, 4,56, 1},
     { 1,11,56, 1},
     { 1,12,56, 1},
     { 1, 4,63, 1},
     { 1,11,63, 1},
     { 1,12,63, 1},
     { 1, 4,68, 1},
     { 1, 4,69, 1},
     { 1, 4,66, 1},
     { 1,11,66, 1},
     { 1,12,66, 1},
     { 1, 4,70, 1},
     { 1,11,70, 1},
     { 1,12,70, 1},
     { 1, 4,67, 1},
     { 1,11,67, 1},
     { 1,12,67, 1},
     { 1, 4,71, 1},
     { 1,11,71, 1},
     { 1,12,71, 1},
     { 1, 5, 5, 1},
     { 1,15,15, 1},
     { 1,16,16, 1},
     { 1, 5, 6, 1},
     { 1, 5,36, 1},
     { 1,15,36, 1},
     { 1,16,36, 1},
     { 1, 5,38, 1},
     { 1, 5,45, 1},
     { 1, 5,46, 1},
     { 1, 5,39, 1},
     { 1, 5,40, 1},
     { 1, 5,41, 1},
     { 1, 5,47, 1},
     { 1, 5,48, 1},
     { 1, 5,50, 1},
     { 1, 5,51, 1},
     { 1, 5,53, 1},
     { 1, 5,60, 1},
     { 1, 5,61, 1},
     { 1, 5,54, 1},
     { 1, 5,55, 1},
     { 1, 5,62, 1},
     { 1, 5,56, 1},
     { 1, 5,63, 1},
     { 1, 5,68, 1},
     { 1, 5,69, 1},
     { 1, 5,66, 1},
     { 1, 5,70, 1},
     { 1, 5,67, 1},
     { 1, 5,71, 1},
     { 1, 5, 9, 1},
     { 1, 5,10, 1},
     { 1, 6, 6, 1},
     { 1, 6, 7, 1},
     { 1, 6, 8, 1},
     { 1, 7, 7, 1},
     { 1, 8, 8, 1},
     { 1, 6,36, 1},
     { 1, 6,38, 1},
     { 1, 6,45, 1},
     { 1, 6,46, 1},
     { 1, 6,40, 1},
     { 1, 6,41, 1},
     { 1, 6,42, 1},
     { 1, 6,43, 1},
     { 1, 6,44, 1},
     { 1, 6,47, 1},
     { 1, 9,47, 1},
     { 1,10,47, 1},
     { 1, 6,48, 1},
     { 1, 6,50, 1},
     { 1, 6,51, 1},
     { 1, 6,53, 1},
     { 1, 6,60, 1},
     { 1, 6,61, 1},
     { 1, 6,58, 1},
     { 1, 6,59, 1},
     { 1, 6,54, 1},
     { 1, 6,55, 1},
     { 1, 6,62, 1},
     { 1, 6,56, 1},
     { 1, 6,63, 1},
     { 1, 6,68, 1},
     { 1, 6,69, 1},
     { 1, 6,66, 1},
     { 1, 6,70, 1},
     { 1, 6,67, 1},
     { 1, 6,71, 1},
     { 1,36, 9, 1},
     { 1,36,10, 1},
     { 1,36,36, 1},
     { 1,36,38, 1},
     { 1,36,45, 1},
     { 1,36,46, 1},
     { 1,36,39, 1},
     { 1,36,40, 1},
     { 1,36,41, 1},
     { 1,36,43, 1},
     { 1,36,44, 1},
     { 1,36,47, 1},
     { 1,36,48, 1},
     { 1,36,50, 1},
     { 1,36,51, 1},
     { 1,36,53, 1},
     { 1,36,60, 1},
     { 1,36,61, 1},
     { 1,36,58, 1},
     { 1,36,59, 1},
     { 1,36,54, 1},
     { 1,36,55, 1},
     { 1,36,62, 1},
     { 1,36,56, 1},
     { 1,36,63, 1},
     { 1,36,68, 1},
     { 1,36,69, 1},
     { 1,36,66, 1},
     { 1,36,70, 1},
     { 1,36,67, 1},
     { 1,36,71, 1},
     { 1,37, 4, 1},
     { 1,37, 5, 1},
     { 1,37, 6, 1},
     { 1,37, 9, 1},
     { 1,37,10, 1},
     { 1,37,11, 1},
     { 1,37,12, 1},
     { 1,37,17, 1},
     { 1,37,18, 1},
     { 1,37,15, 1},
     { 1,37,16, 1},
     { 1,37,36, 1},
     { 1,37,37, 1},
     { 1,37,38, 1},
     { 1,37,39, 1},
     { 1,37,40, 1},
     { 1,37,41, 1},
     { 1,37,42, 1},
     { 1,37,43, 1},
     { 1,37,44, 1},
     { 1,37,45, 1},
     { 1,37,46, 1},
     { 1,37,47, 1},
     { 1,37,48, 1},
     { 1,37,50, 1},
     { 1,37,51, 1},
     { 1,37,53, 1},
     { 1,37,57, 1},
     { 1,37,58, 1},
     { 1,37,59, 1},
     { 1,37,60, 1},
     { 1,37,61, 1},
     { 1,37,54, 1},
     { 1,37,55, 1},
     { 1,37,62, 1},
     { 1,37,56, 1},
     { 1,37,63, 1},
     { 1,37,65, 1},
     { 1,37,68, 1},
     { 1,37,69, 1},
     { 1,37,66, 1},
     { 1,37,70, 1},
     { 1,37,67, 1},
     { 1,37,71, 1},
     { 1,38,38, 1},
     { 1,38,45, 1},
     { 1,38,46, 1},
     { 1,45,46, 1},
     { 1,45,45, 1},
     { 1,46,46, 1},
     { 1,43,43, 1},
     { 1,44,44, 1},
     { 1,43,44, 1},
     { 1,38,43, 1},
     { 1,38,44, 1},
     { 1,38,39, 1},
     { 1,45,39, 1},
     { 1,46,39, 1},
     { 1,38,40, 1},
     { 1,45,40, 1},
     { 1,46,40, 1},
     { 1,38,41, 1},
     { 1,45,41, 1},
     { 1,46,41, 1},
     { 1,41,43, 1},
     { 1,41,44, 1},
     { 1,38,47, 1},
     { 1,45,47, 1},
     { 1,46,47, 1},
     { 1,38,48, 1},
     { 1,45,48, 1},
     { 1,46,48, 1},
     { 1,38,50, 1},
     { 1,45,50, 1},
     { 1,46,50, 1},
     { 1,38,51, 1},
     { 1,45,51, 1},
     { 1,46,51, 1},
     { 1,43,51, 1},
     { 1,43,69, 1},
     { 1,38,53, 1},
     { 1,38,60, 1},
     { 1,38,61, 1},
     { 1,45,61, 1},
     { 1,38,58, 1},
     { 1,38,59, 1},
     { 1,43,53, 1},
     { 1,44,53, 1},
     { 1,43,58, 1},
     { 1,44,59, 1},
     { 1,44,58, 1},
     { 1,43,59, 1},
     { 1,45,60, 1},
     { 1,46,61, 1},
     { 1,38,54, 1},
     { 1,38,55, 1},
     { 1,45,55, 1},
     { 1,46,55, 1},
     { 1,38,56, 1},
     { 1,45,56, 1},
     { 1,46,56, 1},
     { 1,45,62, 1},
     { 1,46,62, 1},
     { 1,38,68, 1},
     { 1,45,68, 1},
     { 1,46,68, 1},
     { 1,38,69, 1},
     { 1,45,69, 1},
     { 1,46,69, 1},
     { 1,38,66, 1},
     { 1,45,70, 1},
     { 1,46,70, 1},
     { 1,38,67, 1},
     { 1,45,71, 1},
     { 1,46,71, 1},
     { 1,39,39, 1},
     { 1,39,40, 1},
     { 1,39,41, 1},
     { 1,39,47, 1},
     { 1,39,48, 1},
     { 1,39,50, 1},
     { 1,39,51, 1},
     { 1,39,53, 1},
     { 1,39,60, 1},
     { 1,39,61, 1},
     { 1,39,54, 1},
     { 1,39,55, 1},
     { 1,39,62, 1},
     { 1,39,56, 1},
     { 1,39,63, 1},
     { 1,39,68, 1},
     { 1,39,69, 1},
     { 1,39,66, 1},
     { 1,39,70, 1},
     { 1,39,67, 1},
     { 1,39,71, 1},
     { 1,40,40, 1},
     { 1,40,41, 1},
     { 1,40,47, 1},
     { 1,40,48, 1},
     { 1,40,50, 1},
     { 1,40,51, 1},
     { 1,40,53, 1},
     { 1,40,60, 1},
     { 1,40,61, 1},
     { 1,40,54, 1},
     { 1,40,55, 1},
     { 1,40,62, 1},
     { 1,40,56, 1},
     { 1,40,63, 1},
     { 1,40,68, 1},
     { 1,40,69, 1},
     { 1,40,66, 1},
     { 1,40,70, 1},
     { 1,40,67, 1},
     { 1,40,71, 1},
     { 1,41,41, 1},
     { 1,41,47, 1},
     { 1,41,48, 1},
     { 1,41,50, 1},
     { 1,41,51, 1},
     { 1,41,53, 1},
     { 1,41,60, 1},
     { 1,41,61, 1},
     { 1,41,54, 1},
     { 1,41,55, 1},
     { 1,41,62, 1},
     { 1,41,56, 1},
     { 1,41,63, 1},
     { 1,41,68, 1},
     { 1,41,69, 1},
     { 1,41,66, 1},
     { 1,41,70, 1},
     { 1,41,67, 1},
     { 1,41,71, 1},
     { 1,47,47, 1},
     { 1,47,48, 1},
     { 1,47,50, 1},
     { 1,47,51, 1},
     { 1,47,53, 1},
     { 1,47,60, 1},
     { 1,47,61, 1},
     { 1,47,54, 1},
     { 1,47,55, 1},
     { 1,47,62, 1},
     { 1,47,56, 1},
     { 1,47,63, 1},
     { 1,47,68, 1},
     { 1,47,69, 1},
     { 1,47,66, 1},
     { 1,47,70, 1},
     { 1,47,67, 1},
     { 1,47,71, 1},
     { 1,48,48, 1},
     { 1,48,50, 1},
     { 1,48,51, 1},
     { 1,48,53, 1},
     { 1,48,60, 1},
     { 1,48,61, 1},
     { 1,48,54, 1},
     { 1,48,55, 1},
     { 1,48,62, 1},
     { 1,48,56, 1},
     { 1,48,63, 1},
     { 1,48,68, 1},
     { 1,48,69, 1},
     { 1,48,66, 1},
     { 1,48,70, 1},
     { 1,48,67, 1},
     { 1,48,71, 1},
     { 1,50,50, 1},
     { 1,50,51, 1},
     { 1,50,53, 1},
     { 1,50,60, 1},
     { 1,50,61, 1},
     { 1,50,54, 1},
     { 1,50,55, 1},
     { 1,50,62, 1},
     { 1,50,56, 1},
     { 1,50,63, 1},
     { 1,50,68, 1},
     { 1,50,69, 1},
     { 1,50,66, 1},
     { 1,50,70, 1},
     { 1,50,67, 1},
     { 1,50,71, 1},
     { 1,51,51, 1},
     { 1,51,69, 1},
     { 1,51,68, 1},
     { 1,51,66, 1},
     { 1,51,70, 1},
     { 1,51,67, 1},
     { 1,51,71, 1},
     { 1,51,53, 1},
     { 1,51,60, 1},
     { 1,51,61, 1},
     { 1,51,54, 1},
     { 1,51,55, 1},
     { 1,51,62, 1},
     { 1,51,56, 1},
     { 1,51,63, 1},
     { 1,53,53, 1},
     { 1,53,60, 1},
     { 1,53,61, 1},
     { 1,53,58, 1},
     { 1,53,59, 1},
     { 1,60,60, 1},
     { 1,61,61, 1},
     { 1,58,58, 1},
     { 1,59,59, 1},
     { 1,58,59, 1},
     { 1,53,54, 1},
     { 1,60,54, 1},
     { 1,61,54, 1},
     { 1,53,55, 1},
     { 1,60,62, 1},
     { 1,61,62, 1},
     { 1,53,56, 1},
     { 1,60,63, 1},
     { 1,61,63, 1},
     { 1,53,68, 1},
     { 1,60,68, 1},
     { 1,61,68, 1},
     { 1,53,69, 1},
     { 1,60,69, 1},
     { 1,61,69, 1},
     { 1,53,66, 1},
     { 1,60,70, 1},
     { 1,61,70, 1},
     { 1,53,67, 1},
     { 1,60,71, 1},
     { 1,61,71, 1},
     { 1,54,54, 1},
     { 1,54,55, 1},
     { 1,54,62, 1},
     { 1,54,56, 1},
     { 1,54,63, 1},
     { 1,54,68, 1},
     { 1,54,69, 1},
     { 1,54,66, 1},
     { 1,54,70, 1},
     { 1,54,67, 1},
     { 1,54,71, 1},
     { 1,55,55, 1},
     { 1,62,62, 1},
     { 1,55,56, 1},
     { 1,62,63, 1},
     { 1,55,66, 1},
     { 1,62,70, 1},
     { 1,55,67, 1},
     { 1,62,71, 1},
     { 1,55,68, 1},
     { 1,62,68, 1},
     { 1,55,69, 1},
     { 1,62,69, 1},
     { 1,56,56, 1},
     { 1,63,63, 1},
     { 1,56,68, 1},
     { 1,63,68, 1},
     { 1,56,69, 1},
     { 1,63,69, 1},
     { 1,56,66, 1},
     { 1,63,70, 1},
     { 1,56,67, 1},
     { 1,63,71, 1},
     { 1,68,68, 1},
     { 1,68,69, 1},
     { 1,68,66, 1},
     { 1,68,70, 1},
     { 1,68,67, 1},
     { 1,68,71, 1},
     { 1,69,69, 1},
     { 1,69,66, 1},
     { 1,69,70, 1},
     { 1,69,67, 1},
     { 1,69,71, 1},
     { 1,66,66, 1},
     { 1,70,70, 1},
     { 1,66,67, 1},
     { 1,70,71, 1},
     { 1,67,67, 1},
     { 1,71,71, 1},
     { 5, 2,68,29},
     { 4, 4,69, 5},
     { 4, 4,36, 2},
     { 2,36,53, 4},
     {36, 5, 2,36},
     { 2,36, 5, 2},
     { 5, 5,36, 2},
     { 5, 5, 2,36},
     { 4,45,56,49},
     { 4,46,56,49},
     {11,45,56,49},
     {11,46,56,49},
     {12,45,56,49},
     {12,46,56,49},
     {26,36, 2,49},
     { 5,69,69, 5},
     { 5,39,47, 6},
     { 5,39,56,49},
     { 6,47,50,27},
     {50,56,51, 5},
     {51,56,51, 5},
     {19, 5, 2,49},
     {25, 5, 2,49},
     {25, 5, 5,25},
     {25, 5, 5, 5},
     {25, 5, 4, 4},
     {27,50, 5, 5},
     {27,50, 2,49},
     { 4, 4, 2,49},
     { 5, 4, 4, 5},
     { 5, 5, 5, 5},
     { 5, 5,39, 5},
     { 5, 5,51, 5},
     { 5, 5,51, 2},
     { 5,51, 5,51},
     { 5,51, 5,41},
     {49, 2,51, 5},
     {51, 5,41, 4},
     {51, 5, 5,51},
     {51, 5, 5,50},
     {50, 5, 5,50},
     {32, 5, 5,32},
     {33, 5, 5,33},
     {34, 5, 5,34},
     {19, 5, 5,51},
     {19, 5, 5,50},
     {19, 5, 5,32},
     {19, 5, 5,33},
     {19, 5, 5,34},
     {25, 5, 5,51},
     {25, 5, 5,50},
     {25, 5, 5,32},
     {25, 5, 5,33},
     {25, 5, 5,34}
};

static float gftor1[MXGTOR][2] = {
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {2.80,  0.0},
     {2.80,  0.0},
     {2.80,  0.0},
     {2.80,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {2.80,  0.0},
     {2.80,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.60,  0.0},
     {0.60,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.30,180.0},
     {1.30,180.0},
     {1.30,180.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {6.80,180.0},
     {6.80,180.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.50,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.70,  0.0},
     {0.70,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {5.00,  0.0},
     {5.00,  0.0},
     {9.50,180.0},
     {9.50,180.0},
     {1.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {2.00,180.0},
     {2.00,180.0},
     {2.00,180.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.20,  0.0},
     {1.20,  0.0},
     {1.20,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.90,  0.0},
     {1.90,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.90,  0.0},
     {0.90,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.85,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.25,180.0},
     {0.25,180.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.30,180.0},
     {0.00,  0.0},
     {1.20,180.0},
     {1.90,180.0},
     {1.70,180.0},
     {0.80,  0.0},
     {0.53,  0.0},
     {0.00,  0.0},
     {2.30,  0.0},
     {2.30,  0.0},
     {2.30,  0.0},
     {2.30,  0.0},
     {2.30,  0.0},
     {2.30,  0.0},
     {2.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.20,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.80,  0.0},
     {0.80,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.15,  0.0},
     {0.25,  0.0},
     {1.90,  0.0},
     {0.00,  0.0},
     {1.90,180.0},
     {0.20,180.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.80,180.0},
     {1.35,180.0},
     {0.00,  0.0},
     {1.40,180.0},
     {2.50,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {0.00,  0.0},
     {1.20,180.0},
     {0.45,180.0},
     {0.00,180.0},
     {0.25,  0.0},
     {0.25,  0.0},
     {0.19,  0.0},
     {0.25,  0.0},
     {0.55,  0.0},
     {0.25,  0.0},
     {0.25,  0.0},
     {0.19,  0.0},
     {0.25,  0.0},
     {0.55,  0.0}
};

static float gftor2[MXGTOR][2] = {
     {0.300, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {2.175, 180.000},
     {2.175, 180.000},
     {2.175, 180.000},
     {2.175, 180.000},
     {2.175, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {3.625, 180.000},
     {2.875, 180.000},
     {2.875, 180.000},
     {2.500, 180.000},
     {4.150, 180.000},
     {4.000, 180.000},
     {4.000, 180.000},
     {0.200, 180.000},
     {0.200, 180.000},
     {1.450, 180.000},
     {0.450, 180.000},
     {2.300, 180.000},
     {2.700, 180.000},
     {2.000, 180.000},
     {6.650, 180.000},
     {2.000, 180.000},
     {2.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {1.550, 180.000},
     {1.350, 180.000},
     {1.350, 180.000},
     {1.000,   0.000},
     {1.000,   0.000},
     {2.250, 180.000},
     {3.100, 180.000},
     {0.200, 180.000},
     {0.200, 180.000},
     {0.500,   0.000},
     {0.500,   0.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {1.000, 180.000},
     {1.000, 180.000},
     {4.000, 180.000},
     {4.000, 180.000},
     {4.000, 180.000},
     {0.000,   0.000},
     {2.550, 180.000},
     {0.650, 180.000},
     {4.150, 180.000},
     {4.150, 180.000},
     {4.150, 180.000},
     {0.800, 180.000},
     {0.800, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {0.300, 180.000},
     {0.000,   0.000},
     {0.625, 180.000},
     {1.700, 180.000},
     {1.700, 180.000},
     {0.675, 180.000},
     {0.750, 180.000},
     {1.050, 180.000},
     {1.050, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {0.950, 180.000},
     {0.950, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {4.750, 180.000},
     {0.450, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {0.325,   0.000},
     {0.325,   0.000},
     {0.325,   0.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {1.4333, 180.000},
     {1.4333, 180.000},
     {1.4333, 180.000},
     {0.500, 180.000},
     {1.100, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {0.600,   0.000},
     {0.600,   0.000},
     {0.600,   0.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {1.2667, 180.000},
     {1.2667, 180.000},
     {1.2667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.2667, 180.000},
     {0.2667, 180.000},
     {0.2667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {3.625, 180.000},
     {3.625, 180.000},
     {3.625, 180.000},
     {1.000, 180.000},
     {1.000, 180.000},
     {0.450, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {1.750,   0.000},
     {0.300, 180.000},
     {4.800, 180.0},
     {4.800, 180.0},
     {4.800, 180.0},
     {1.050, 180.000},
     {1.050, 180.000},
     {1.050, 180.000},
     {0.600, 180.000},
     {0.900, 180.000},
     {0.900, 180.000},
     {0.600, 180.000},
     {0.600, 180.000},
     {0.600, 180.000},
     {4.800, 180.000},
     {4.800, 180.000},
     {0.000, 180.000},
     {0.525, 180.000},
     {0.525, 180.000},
     {1.4667, 180.000},
     {1.4667, 180.000},
     {0.000, 180.000},
     {0.400, 180.000},
     {0.300,   0.000},
     {0.300,   0.000},
     {1.300, 180.000},
     {1.300, 180.000},
     {1.650, 180.000},
     {1.650, 180.000},
     {1.150,   0.000},
     {0.400,   0.000},
     {0.400,   0.000},
     {0.400,   0.000},
     {1.075,   0.000},
     {0.950,   0.000},
     {0.700,   0.000},
     {4.800, 180.000},
     {4.800, 180.000},
     {1.100,   0.000},
     {1.375, 180.000},
     {1.500,   0.000},
     {1.100,   0.000},
     {1.000, 180.000},
     {1.000, 180.000},
     {4.800, 180.000},
     {4.800, 180.000},
     {1.000, 180.000},
     {2.250,   0.000},
     {0.325,   0.000},
     {0.325,   0.000},
     {2.200, 180.000},
     {2.200, 180.000},
     {1.100,   0.000},
     {1.500,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {1.100, 180.000},
     {1.100, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {0.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {1.200, 180.000},
     {1.200, 180.000},
     {4.000, 180.000},
     {4.000, 180.000},
     {4.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {6.100, 180.000},
     {6.100, 180.000},
     {6.100, 180.000},
     {8.000, 180.000},
     {8.000, 180.000},
     {8.000, 180.000},
     {1.700, 180.000},
     {1.700, 180.000},
     {1.700, 180.000},
     {4.800, 180.000},
     {4.800, 180.000},
     {2.800, 180.000},
     {2.800, 180.000},
     {2.800, 180.000},
     {0.750, 180.000},
     {0.750, 180.000},
     {0.750, 180.000},
     {3.200, 180.000},
     {3.200, 180.000},
     {3.200, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {4.800, 180.000},
     {4.800, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {5.400, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.100, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.650, 180.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.100, 180.000},
     {2.100, 180.000},
     {2.100, 180.000},
     {2.800, 180.000},
     {2.800, 180.000},
     {2.800, 180.000},
     {6.650, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.250,   0.000},
     {0.000,   0.000},
     {1.600,   0.000},
     {1.900,   0.000},
     {4.000, 180.000},
     {2.200,   0.000},
     {1.800,   0.000},
     {3.200, 180.000},
     {3.200, 180.000},
     {3.200, 180.000},
     {2.350,   0.000},
     {2.100, 180.000},
     {2.100, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {3.100,   0.000},
     {2.600,   0.000},
     {3.750,   0.000},
     {3.750,   0.000},
     {3.1333,   0.000},
     {3.1333,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.900,   0.000},
     {1.200,   0.000},
     {6.000, 180.000},
     {1.000,   0.000},
     {0.650,   0.000},
     {1.000, 180.000},
     {1.000, 180.000},
     {1.000, 180.000},
     {1.450,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.8333, 180.000},
     {0.8333, 180.000},
     {1.800,   0.000},
     {7.800,   0.000},
     {1.050,   0.000},
     {1.050,   0.000},
     {3.6667, 180.000},
     {3.6667, 180.000},
     {0.000,   0.000},
     {2.550, 180.000},
     {1.500,   0.000},
     {0.000,   0.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {2.350,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.800,   0.000},
     {0.800,   0.000},
     {1.600,   0.000},
     {2.100,   0.000},
     {0.750,   0.000},
     {0.750,   0.000},
     {0.100, 180.000},
     {0.100, 180.000},
     {1.800, 180.000},
     {3.900, 180.000},
     {3.000, 180.000},
     {0.300, 180.000},
     {0.300, 180.000},
     {0.300, 180.000},
     {1.900, 180.000},
     {0.575, 180.000},
     {0.575, 180.000},
     {2.400,   0.000},
     {2.400,   0.000},
     {2.300, 180.000},
     {2.700, 180.000},
     {2.600, 180.000},
     {2.600, 180.000},
     {0.3333,   0.000},
     {0.3333,   0.000},
     {1.600,   0.000},
     {1.600,   0.000},
     {1.500, 180.000},
     {1.500, 180.000},
     {1.500, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.400,   0.000},
     {2.400,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.200,   0.000},
     {1.800,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {1.200, 180.000},
     {1.200, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {3.000, 180.000},
     {2.200,   0.000},
     {1.050, 180.000},
     {1.050, 180.000},
     {0.800,   0.000},
     {0.800,   0.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {6.600, 180.000},
     {1.200, 180.000},
     {1.200, 180.000},
     {7.200, 180.000},
     {7.200, 180.000},
     {7.200, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {6.650, 180.000},
     {2.450,   0.000},
     {2.450,   0.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {1.400, 180.000},
     {6.650, 180.000},
     {1.500,   0.000},
     {1.500,   0.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {1.8333, 180.000},
     {1.8333, 180.000},
     {4.600,   0.000},
     {0.000,   0.000},
     {3.850,   0.000},
     {3.850,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {6.650, 180.000},
     {1.450, 180.000},
     {6.650, 180.000},
     {0.3167, 180.000},
     {6.650, 180.000},
     {0.000,   0.000},
     {6.650, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.600, 180.000},
     {0.600, 180.000},
     {6.6667, 180.000},
     {0.600,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {3.800, 180.000},
     {3.800, 180.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {6.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {4.6667, 180.000},
     {4.6667, 180.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {3.0667, 180.000},
     {3.0667, 180.000},
     {6.650, 180.000},
     {0.000,   0.000},
     {6.6667, 180.000},
     {4.3333, 180.000},
     {6.6667, 180.000},
     {0.1556, 180.000},
     {2.250, 180.000},
     {1.100, 180.000},
     {0.650, 180.000},
     {1.000, 180.000},
     {2.000, 180.000},
     {0.850, 180.000},
     {0.000,   0.000},
     {0.070,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.500, 180.0},
     {3.500,   0.000},
     {1.900,   0.000},
     {3.000, 180.0},
     {1.500,   0.000},
     {1.200,   0.000},
     {1.200,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {2.300, 180.000},
     {2.175, 180.000},
     {6.650, 180.000},
     {0.250, 180.000},
     {0.480, 180.000},
     {0.100, 180.000},
     {0.000,   0.000},
     {0.850, 180.000},
     {0.650,   0.000},
     {2.700, 180.000},
     {0.000,   0.000},
     {1.175,   0.000},
     {1.175,   0.000},
     {1.175,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000},
     {0.000,   0.000}
};

static float gftor3[MXGTOR][2] = {
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.156,   0.000},
     {  0.156,   0.000},
     {  0.156,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.300,   0.000},
     {  0.156,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.167,   0.000},
     {  0.383,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.133,   0.000},
     {  0.133,   0.000},
     {  0.133,   0.000},
     {  0.022,   0.000},
     {  0.022,   0.000},
     {  0.250,   0.000},
     {  0.333,   0.000},
     {  0.200,   0.000},
     {  0.200,   0.000},
     { 0.1444,   0.000},
     { 0.1444,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000, 180.000},
     {  0.000, 180.000},
     {  0.000,  80.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.500,   0.000},
     {  1.500,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.000, 180.000},
     {  1.000, 180.000},
     {  1.000, 180.000},
     {  1.000, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.500, 180.000},
     {  1.500, 180.000},
     {  0.000,   0.000},
     {  0.500, 180.000},
     {  0.500, 180.000},
     {  0.000,   0.000},
     {  0.250,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     { 0.1888,   0.000},
     { 0.2333,   0.000},
     { 0.1833,   0.000},
     { 0.0833, 180.000},
     { 0.3333,   0.000},
     { 0.5666,   0.000},
     { 1.6666, 180.000},
     { 1.6666, 180.000},
     { 1.6666, 180.000},
     {  0.150,   0.000},
     {  0.050,   0.000},
     {  0.050,   0.000},
     { 0.0888,   0.000},
     { 0.0888,   0.000},
     { 0.6666,   0.000},
     { 0.3333,   0.000},
     { 0.2833,   0.000},
     { 0.2833,   0.000},
     { 0.1333,   0.000},
     { 0.1333,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.100,   0.000},
     {  1.100,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.800, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.175,   0.000},
     {  1.175,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.100, 180.000},
     {  0.100, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.400,   0.000},
     {  0.400,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.400, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     { 0.5333,   0.000},
     { 0.5333,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.650,   0.000},
     {  1.650,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.400, 180.000},
     {  0.400, 180.000},
     {  0.500,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  1.150,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     { 0.2666,   0.000},
     { 0.2666,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     { 0.1166,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.300,   0.000},
     {  0.300,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     { 0.2666,   0.000},
     {  0.000,   0.000},
     { 0.2777,   0.000},
     {  5.600,   0.000},
     {  5.300,   0.000},
     {  0.700,   0.000},
     {  0.700,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.300,   0.000},
     {  0.300,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.625,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.700, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.150, 180.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.600,   0.000},
     {  1.900,   0.000},
     {  2.300,   0.000},
     {  0.000,   0.000},
     {  0.250,   0.000},
     {  0.250,   0.000},
     {  0.080, 180.000},
     {  0.080, 180.000},
     {  0.150,   0.000},
     {  0.160,   0.000},
     {  0.380, 180.000},
     {  0.160,   0.000},
     {  0.000,   0.000},
     {  0.300,   0.000},
     {  0.000,   0.000},
     {  0.180,   0.000},
     {  0.300,   0.000},
     {  0.383,   0.000},
     {  0.383,   0.000},
     {  0.100,   0.000},
     {  0.383,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.144,   0.000},
     {  0.144,   0.000},
     {  0.144,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000},
     {  0.000,   0.000}
};

static float gftor4[MXGTOR][2] = {
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     { 0.35, 180.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.4, 180.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.5, 180.0},
     {  0.1,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0},
     {  0.0,   0.0}
};

#define DIFFCOO 1.0

void IniTri(TRISTRU *Tri)
{
   int i,j;

   Tri->d12 = 0.0;
   Tri->d13 = 0.0;
   Tri->d23 = 0.0;
   Tri->e12 = 0.0;
   Tri->eint = 0.0;
   Tri->etot = 0.0;
   Tri->overl = 0.0;
   Tri->coo = NULL;
   Tri->frag = 0;
   Tri->triS = 0;
   Tri->conf = 0;
   Tri->nconf = 0;
   Tri->spec = 0;
   Tri->done = 0;
   Tri->dorot = 0;
   Tri->itry = -1;
   Tri->oneline = 0;

   for (i = 0; i < 3; i++) {
	Tri->p1[i] = 0.0;
	Tri->p2[i] = 0.0;
	Tri->p3[i] = 0.0;
	Tri->P1[i] = 0.0;
	Tri->P2[i] = 0.0;
	Tri->P3[i] = 0.0;
	Tri->p1c[i] = 0.0;
	Tri->p2c[i] = 0.0;
	Tri->p3c[i] = 0.0;
	Tri->Cen[i] = 0.0;
	Tri->CenO[i] = 0.0;
	Tri->Out[i] = 0.0;
	Tri->OutO[i] = 0.0;
	Tri->OutOrg[i] = 0.0;
	Tri->t[i] = 0.0;
	Tri->lig[i] = 0;
	Tri->ohlig[i] = 0;
	Tri->prot[i] = 0;
	Tri->oh[i] = NULL;
	Tri->frags[i] = 0;
	Tri->grp[i] = 0;
	Tri->idx[i] = 0;
	Tri->e12c[i] = 0.0;
   }

   for (i = 0; i < 4; i++) {
      for (j = 0; j < 4; j++) {
	Tri->R1[i][j] = 0.0;
	Tri->R2[i][j] = 0.0;
	Tri->R3[i][j] = 0.0;
      }
   }

}

void TriAll(TRISTRU **Tri)
{
   *Tri = (TRISTRU *) malloc(sizeof(TRISTRU));
   memcpy(*Tri,&TriIni,sizeof(TRISTRU));
}

void IniCHK()
{
   int i;

   for (i=0; i < MAXCHK; i++) {
	TriAll(&TriCHK[i]);
	allConf(&TriCHK[i]->coo,ndocka);
   }
}

void InitIncr(INCRSTRU *Inc)
{
   int i,j;

   Inc->area = AREAINI;
   Inc->q0 = 0.0;
   Inc->q1 = 0.0;
   Inc->q2 = 0.0;
   Inc->q3 = 0.0;
   Inc->nfrag = 0;
   Inc->n = 0;
   Inc->npts = 0;
   Inc->link = -1;
   Inc->conf = 0;
   Inc->nconf = 0;
   Inc->res = 0;
   Inc->ohsame = 0;
   Inc->ohlig = 0;
   Inc->type = 0;
   Inc->points = NULL;

   for (i = 0; i < 4; i++) {
	Inc->frag[i] = 0;
	Inc->atom[i] = 0;
   }

   Inc->ConfArr = NULL;

   for (i = 0; i < 3; i++) {
	Inc->ORI[i] = 0.0;
   }

   for (i = 0; i < 4; i++) {
      for (j = 0; j < 3; j++) {
	Inc->c[i][j] = 0.0;
      }
   }

}

void IncrAll(INCRSTRU **typ)
{
   *typ =  (INCRSTRU *) malloc((sizeof(INCRSTRU)));
   memcpy(*typ,&IncrIni,sizeof(INCRSTRU));
}

void CalcETris(int opt);

void alldck(xyzc,ZSizep)
COOSTRU *xyzc;
int *ZSizep;
{
   int memstat;
   double d;
   int i;
   int j;
   int ZSize;

   memstat = 1;
   ZSize = *ZSizep;

   if ((xyzc->coo = (double *) malloc((sizeof d)*ZSize*3)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->qat = (double *) malloc((sizeof d)*ZSize)) == NULL) {
	memstat = 0;
   }


   if ((xyzc->ianz = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->iaton = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->iconn = (int *) malloc((sizeof i)*ZSize*(MXCON+1))) == NULL) {
	memstat = 0;
   }

   if ((xyzc->iatclr = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->iresid = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->isurf = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->lwrit = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->lring = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->icont = (int *) malloc((sizeof i)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->ityp = (int *) malloc((sizeof j)*ZSize)) == NULL) {
	memstat = 0;
   }

   if ((xyzc->ipdbt = (int *) malloc((sizeof j)*ZSize)) == NULL) {
	memstat = 0;
   }

   xyzc->rzp   = NULL;
   xyzc->ixp    = NULL;
   xyzc->iyp    = NULL;
   xyzc->inat   = NULL;

   if (!memstat) {
	fprintf(stderr,"Out of memory alldck\n");
   } else {
	xyzc->iatoms = 0;
	for (i=0; i < ZSize; i++) {
		xyzc->qat[i] = 0.0;
		xyzc->ianz[i] = 0;
		xyzc->ityp[i] = 0;
		xyzc->lring[i] = 0;
		xyzc->lwrit[i] = 0;
		xyzc->iaton[i] = 2;
		xyzc->iatclr[i] = 1;
	}
	xyzc->mxnat = &mxliga;
	xyzc->mxorg = 1;
   }
}

int ChkLig(int ATMselp)
{
  if (ATMselp < lintp && DCKLIGPROC) return 1;
  return 0;
}

int ChkProt(int ATMselp)
{
  if (ATMselp < nintp && DCKPROTPROC) return 1;
  return 0;
}

void TriPurge(int itri)
{
   int i;

   if (TriArr[itri] == NULL) return;

   for (i = 0; i < ntris; i++) {
	if (TriArr[itri] != NULL) {
	   if (TriArr[i] != NULL && i != itri) {
		if (TriArr[itri] == TriArr[i]) TriArr[i] = NULL;
	   }
	}
   }
   
}

void UniqList()
{
   int i;

   for (i = 0; i < ntris; i++) {
	if (TriArr[i] != NULL) TriPurge(i);
   }
}

void TriSafeFree(int itri)
{
   int i,fnd;

   fnd = 0;

   if (TriArr[itri] == NULL) return;

   for (i = 0; i < ntris; i++) {
	if (TriArr[itri] != NULL) {
	   if (TriArr[i] != NULL && i != itri) {
		if (TriArr[itri] == TriArr[i]) TriArr[i] = NULL;
	   }
	}
   }

   
   safefree((void **) &TriArr[itri]);

   TriArr[itri] = NULL;
}

void TriSafeFreeTxt(int itri, char *routine, char *reason)
{
   int i,fnd;

   fnd = 0;

   if (TriArr[itri] == NULL) return;

   fnd = PrtConf(TriArr[itri],itri);
   if (!fnd) fnd = Match_tri(TriArr[itri],8,24,14,51,235,249);

   if (fnd && debugdck) {
	fprintf(stderr,"TriSafeFree: %s\n\n\
		+++++++++++++++++++++++++++++++++++++++\n\
		Input ligand pose eliminated: itri [%d]\n\
		%s\n\
		ligand combo itri [%d] = lig %d,%d,%d prot %d,%d,%d conf %d dcnt %f\n\
		+++++++++++++++++++++++++++++++++++++++\n\n",
		routine,itri,reason,itri,TriArr[itri]->lig[0],
		TriArr[itri]->lig[1],TriArr[itri]->lig[2],
		TriArr[itri]->prot[0],TriArr[itri]->prot[1],
		TriArr[itri]->prot[2],TriArr[itri]->conf,TriArr[itri]->dcnt);
   }

   for (i = 0; i < ntris; i++) {
	if (TriArr[itri] != NULL) {
	   if (TriArr[i] != NULL && i != itri) {
		if (TriArr[itri] == TriArr[i]) TriArr[i] = NULL;
	   }
	}
   }

   
   safefree((void **) &TriArr[itri]);

   TriArr[itri] = NULL;
}

void TriCooSafeFree(int itri)
{
   int i;

   if (TriArr[itri] == NULL) return;
   if (TriArr[itri]->coo == NULL) return;

   for (i = 0; i < ntris; i++) {
	if (i != itri) {
	   if (TriArr[i] != NULL) {
	     if (TriArr[i]->coo != NULL) {
		if (TriArr[itri]->coo == TriArr[i]->coo) {
		   safefree((void **) &TriArr[i]->coo);
		}
	     }
	   }
	}
   }

   safefree((void **) &TriArr[itri]->coo);

   TriArr[itri]->coo = NULL;
}

int FillOptD(int *iclos)
{
   int k,n;

   n = 0;

   for (k=0; k<*xyzp->iatoms; k++) {
	   if (xyzp->iclos[k] == 1) {
		iclos[k] = 1; n++;
	   } else {
		iclos[k] = 0;
	   }
   }


   return(n);
}

int FillOpt(int *iclos,int i)
{
   int j,k,n,ires,kmin1,kmin2,irest;
   float dd,tt,dmin1,dmin2;

   dmin1 = 10000.0;
   dmin2 = 10000.0;
   kmin1 = -1;
   kmin2 = -1;
   n = 0;

   if (DCKMETH == 0) {
	for (k=0; k<*xyzp->iatoms; k++) {
	   if (xyzp->iclos[k] == 1) {
		iclos[k] = 1; n++;
	   } else {
		iclos[k] = 0;
	   }
	}

   }

   for (k=0; k<*xyzp->iatoms; k++) {

	dd = 0.0;
	if (DCKMETH != 0) iclos[k] = 0;

	if (xyzp->iresid[k] > 0) {
	    for (j=0; j<3; j++) {
		tt = ((float) xyzp->coo[k*3+j] - TriArr[i]->Cen[j]);
		dd = dd + tt*tt;
	    }
	    dd = sqrt(dd)*toangs;
	    if (dd < OPTRadius) {
		iclos[k] = 1;
		n++;
		if (dd < dmin1) {
		   dmin1 = dd;
		   kmin1 = k;
		} else {
		   if (dd < dmin2) {
			dmin2 = dd;
			kmin2 = k;
		   }
		}
	    }
	}
   }

   if (kmin1 != -1) iclos[kmin1] = 2;
   if (kmin2 != -1) iclos[kmin2] = 2;

   return(n);
}

int FillFull(int *iclos,int i)
{
   int j,k,l,ia,n;
   float dd,tt,dmin;

// This different from FillOpt in that FillOpt only looks
// for protein atoms close to TriArr[i]->Cen
// FillCOpt looks at atoms close to singleb.sng[l][0]

   dmin = 10000.0;
   n = 0;

   for (k=0; k<*xyzp->iatoms; k++) {

	dd = 0.0;
	iclos[k] = 0;

	if (xyzp->iresid[k] > 0) {
	  for (l=0; l < ndocka; l++) {
	    for (j=0; j<3; j++) {
		tt = ((float) xyzp->coo[k*3+j] - TriArr[i]->coo[l*3+j]);
		dd = dd + tt*tt;
	    }
	    dd = sqrt(dd)*toangs;
	    if (dd < OPTRadius) {
		iclos[k] = 1;
		n++;
		if (dd < dmin) {
		   dmin = dd;
		}
	    }
	  }
	}
   }

   return(n);
}

void FillClos(int *iclos,int itri)
{
   int j,k,l,ia;
   float dd,tt,dmin;

// This different from FillOpt in that FillOpt only looks
// for protein atoms close to TriArr[i]->Cen
// FillClos looks at atoms close to all atoms of the ligand pose

   if (DCKMETH == 0) {
	for (k=0; k<*xyzp->iatoms; k++) {
	   if (xyzp->iclos[k] == 1) {
		iclos[k] = 1;
	   } else {
		iclos[k] = 0;
	   }
	}
   }

   for (k=0; k<*xyzp->iatoms; k++) {

	dd = 0.0;
	if (DCKMETH != 0) iclos[k] = 0;

	if (xyzp->iresid[k] > 0) {
	  for (l=0; l < ndocka; l++) {
	    for (j=0; j<3; j++) {
		tt = ((float) xyzp->coo[k*3+j] - TriArr[itri]->coo[l*3+j]);
		dd = dd + tt*tt;
	    }
	    dd = sqrt(dd)*toangs;
	    if (dd < OPTRadius) iclos[k] = 1;
	  }
	}
   }

}

int ChkBump(int *iclos,int i,int opt)
{
   int j,k,l,kmin,jmin,il,it;
   float dd,dl,tt,dmin,vdwr1,vdwr2,dir[3],ddif,xx;

   dmin = 10000.0;
   kmin = -1;
   jmin = -1;
   vdwr1 = -1.0;
   vdwr2 = -1.0;

   for (j=0; j<*xyzp->iatoms; j++) {
	if (iclos[j] == 2) {
	   kmin = j;
	   it = (int) xyzp->ityp[j];
	   if (it > 0) {
	      il = chgvdwptr->ambvdt[it-1]-1;
	      vdwr1 = (float) chgvdwptr->ambvw1[il];
	      iclos[j] = 1;
	   }
	   break;
	}
   }


   if (kmin >= 0) {
	for (j=0; j < ndocka; j++) {
	
	   if (DCKxyz.ianz[j] != 1) {
		dd = 0.0;
		for (k=0; k<3; k++) {
		   tt = (float) (TriArr[i]->coo[j*3+k] - xyzp->coo[kmin*3+k]);
		   tt = tt*toangs;
		   dd = dd + tt*tt;
		}
		dd = sqrt(dd);

		if (dd < dmin) {
		   dmin = dd;
		   jmin = j;
		}
	   }
	}
   }

   if (jmin != -1 && kmin >= 0) {
	
	it = (int) singleb.ityp[jmin];
	if (it < 0) {
	   il = ABS(it) - 1;
	   vdwr2 = (float) chgvdwptr->gfvdw[il][0];
	}

	dd = 0.0;
	for (k=0; k<3; k++) {
	   dir[k] = (float) (TriArr[i]->coo[jmin*3+k] - xyzp->coo[kmin*3+k]);
	   dir[k] = dir[k]*toangs;
	   dd = dd + dir[k]*dir[k];
	}
	dd = sqrt(dd);

	if (vdwr1 != -1.0 && vdwr2 != -1.0) {
	   if (dd < vdwr1+vdwr2) {

		if (opt) {

		   dl = veclen(dir);
		   for (k=0; k<3; k++) dir[k] = dir[k]/dl;
	   
		   ddif = vdwr1 + vdwr2 - dd + 0.1;

		   for (k=0; k<3; k++) dir[k] = dir[k]*ddif/toangs;

		   for (j=0; j < ndocka; j++) {
			for (k=0; k<3; k++) {
			   TriArr[i]->coo[j*3+k] = TriArr[i]->coo[j*3+k] 
			   + (double) dir[k];
			}
		   }

		   for (k=0; k<3; k++) {
			TriArr[i]->Cen[k] = TriArr[i]->Cen[k] + dir[k];
		   }

		} else {
		   return(1);
		}

	   }
	}
   }

   dmin = 10000.0;
   kmin = -1;
   jmin = -1;

   for (j=0; j<*xyzp->iatoms; j++) {
	if (iclos[j] == 2) {
	   kmin = j;
	   it = (int) xyzp->ityp[j];
	   if (it > 0) {
		il = chgvdwptr->ambvdt[it-1]-1;
		vdwr1 = (float) chgvdwptr->ambvw1[il];
		iclos[j] = 1;
	   }
	   break;
	}
   }


   if (kmin >= 0) {
	for (j=0; j < ndocka; j++) {
	
	   if (DCKxyz.ianz[j] != 1) {
		dd = 0.0;
		for (k=0; k<3; k++) {
		   tt = (float) (TriArr[i]->coo[j*3+k] - xyzp->coo[kmin*3+k]);
		   tt = tt*toangs;
		   dd = dd + tt*tt;
		}
		dd = sqrt(dd);

		if (dd < dmin) {
		   dmin = dd;
		   jmin = j;
		}
	   }
	}
   }

   if (jmin != -1 && kmin >= 0) {
	
	it = (int) singleb.ityp[jmin];
	if (it < 0) {
	   il = ABS(it) - 1;
	   vdwr2 = (float) chgvdwptr->gfvdw[il][0];
	}

	dd = 0.0;
	for (k=0; k<3; k++) {
	   dir[k] = (float) (TriArr[i]->coo[jmin*3+k] - xyzp->coo[kmin*3+k]);
	   dir[k] = dir[k]*toangs;
	   dd = dd + dir[k]*dir[k];
	}
	dd = sqrt(dd);

	if (vdwr1 != -1.0 && vdwr2 != -1.0) {
	   if (dd < vdwr1+vdwr2) {

		if (opt) {

		   dl = veclen(dir);
		   for (k=0; k<3; k++) dir[k] = dir[k]/dl;
	   
		   ddif = vdwr1 + vdwr2 - dd;

		   for (k=0; k<3; k++) dir[k] = dir[k]*ddif/toangs;

		   for (j=0; j < ndocka; j++) {
		      for (k=0; k<3; k++) {
			TriArr[i]->coo[j*3+k] = TriArr[i]->coo[j*3+k] 
			   + (double) dir[k];
		      }
		   }

		   for (k=0; k<3; k++) {
			TriArr[i]->Cen[k]  = TriArr[i]->Cen[k] + dir[k];
		   }
		} else {
		   return(1);
		}

	   }
	}
   }
   return(0);
}

int typchk(silent)
int silent;
{
   int i,j;

   j = 0;
   for ( i = 0; i < *xyzp->iatoms; i++ ) {
	   if (xyzp->ianz[i] < 99 &&  xyzp->ityp[i] == 0) {
		if (!silent) {
		   if (xyzp->iresid[i] > 0) {
			fprintf(stderr,"AtomNr. %d %s %s untyped\n",i+1,
			elements[xyzp->ianz[i]],
			AminoAcids[calfptr->iamino[xyzp->iresid[i]-1]-1]);
			fprintf(stderr,"Coordinates (Ang) %#9.3f,%#9.3f,%#9.3f\n",
			   xyzp->coo[i*3]*toangs,
			   xyzp->coo[i*3+1]*toangs,
			   xyzp->coo[i*3+2]*toangs);
		   } else if (xyzp->iresid[i] < -3) {
			fprintf(stderr,"AtomNr. %d %s %s untyped\n",i+1,
			elements[xyzp->ianz[i]],
			hetptr.HetAtm[ABS(xyzp->iresid[i])]);
			fprintf(stderr,"Coordinates (Ang) %#9.3f,%#9.3f,%#9.3f\n",
			   xyzp->coo[i*3]*toangs,
			   xyzp->coo[i*3+1]*toangs,
			   xyzp->coo[i*3+2]*toangs);
		   }
		}
		j++;
	   }

   }
   return(j);

}

void dotyp_()
{

	dotyd_(
	xyzp->ianz,xyzp->iaton,xyzp->iatclr,xyzp->iconn,xyzp->iresid,
	xyzp->lwrit,xyzp->lring,xyzp->ityp,xyzp->coo,xyzp->qat,xyzp->icont,
	calfptr->icalf,&calfptr->ncalf,calfptr->ianf,calfptr->islu,
	&calfptr->nchain,calfptr->iamino,&calfptr->ishoh);

}

int typit(ff,silent)
int ff;
int silent;
{
   int iretval,retype;
   char mess[64];

   iretval = 0;
   retype = 0; 

   if (*fftyp != ff) {
	*fftyp = ff;
	retype = 1;
   } else {
	if (typchk(silent)) retype = 1;
   }
   
   if (retype) {
	dotyp_();
	iretval = typchk(silent);

	if (!silent) {
	   sprintf(mess,"(Re)typing %s",ForceFields[*fftyp]);
	}
   }
   return(iretval);
}

void AssChg(float *q)
{
// asssign amber charges to protein atoms
   int i,it;

   typit(7,1);

   for (i=0; i < *xyzp->iatoms; i++) {
	it = (int) xyzp->ityp[i];
	if (! (it < 0)) {
	   q[i] = (float) chgvdwptr->ambchg[it-1];
	} else {
	   q[i] = 0.0;
	}
   }
}

void AssVDW(float *vdwr, float *vdwe)
{
// asssign amber van der Waals parameters to protein atoms
   int i,it,il;

   for (i=0; i < *xyzp->iatoms; i++) {
	it = (int) xyzp->ityp[i];
	if (! (it <= 0)) {
	   il = chgvdwptr->ambvdt[it-1]-1;
	   vdwr[i] = (float) chgvdwptr->ambvw1[il];
	   vdwe[i] = (float) chgvdwptr->ambvw2[il];
	} else {
	   vdwr[i] = 0.0;
	   vdwe[i] = 0.0;
	}
   }
}

void AssVDWL(float *vdwr, float *vdwe,float *q)
{

// asssign gaff van der Waals parameters and charges from read in ligand file
// to lignd

   int i,it,il;

   for (i=0; i < ndocka; i++) {
	it = (int) singleb.ityp[i];
	il = it - 1;
	vdwr[i] = (float) chgvdwptr->gfvdw[il][0];
	vdwe[i] = (float) chgvdwptr->gfvdw[il][1];
	q[i] = (float) DCKxyz.qat[i];

   }
}

#define MXDIH 13

static int jact[MXDIH][MXLIGA];
static int jopt[MXDIH][MXLIGA];

//#define DCKSCLASH 3.0
#define DCKSCLASH 7.0
#define BIGD 10000.0
#define IBIG -10000

float CalClash(iclos,itri,vdwr,vdwrl,coo,idih)
int *iclos;
int itri;
float *vdwr;
float *vdwrl;
double *coo;
int idih;
{
   int i,j,k;
   float tt,dd,dmin,vdwr1,vdwr2,vsum;

   for (i=0; i<*xyzp->iatoms; i++) {

	vdwr1 = vdwr[i];

	if (iclos[i]) {
	   for (j=0; j < ndocka; j++) {

	     if (jopt[idih][j] == 1) {
		vdwr2 = vdwrl[j];
		if (DCKxyz.ianz[j] == 1) vdwr2 = 0.0;
		vsum = vdwr1 + vdwr2;
		vsum = vsum*vsum;
		dd = 0.0;

		for (k=0; k<3; k++) {
		   tt = (float) (coo[j*3+k] - xyzp->coo[i*3+k]);
		   tt = tt*toangs;
		   dd = dd + tt*tt;
		}

		if (dd+DCKSCLASH < vsum) return(BIGD);
	     }
	   }
	}
   }

   return(0.0);
}

int AllArr(float **q, float **vdwr, float **vdwe, int **iclos, float **F)
{
   int i;
   float f;

   if ((*q = (float *) malloc((sizeof f)*(*xyzp->iatoms))) == NULL) {
	return(0);
   }

   if ((*vdwr = (float *) malloc((sizeof f)*(*xyzp->iatoms))) == NULL) {
	return(0);
   }

   if ((*vdwe = (float *) malloc((sizeof f)*(*xyzp->iatoms))) == NULL) {
	return(0);
   }

   if ((*iclos = (int *) malloc((sizeof i)*(*xyzp->iatoms))) == NULL) {
	return(0);
   }

   if ((*F = (float *) malloc(3*(sizeof f)*(*xyzp->iatoms))) == NULL) {
	return(0);
   }

   return(1);
}

int AllVDWArr(float **q, float **vdwr, float **vdwe, int size)
{
   int i;
   float f;

   if ((*q = (float *) malloc((sizeof f)*(size))) == NULL) {
	return(0);
   }

   if ((*vdwr = (float *) malloc((sizeof f)*(size))) == NULL) {
	return(0);
   }

   if ((*vdwe = (float *) malloc((sizeof f)*(size))) == NULL) {
	return(0);
   }

   return(1);
}

void Newxyz(float a, float *dir, float *cwxyz)
{
   float z[3],E;
   int l,j;

   for (l=0; l < 3; l++) {
	z[l] = a*dir[l];
   }

   for (j=0; j < ndocka; j++) {
	for (l=0; l < 3; l++) cwxyz[3*j+l] = cwxyz[3*j+l] + z[l];
   }

// return a not correct, it needs to return E as function of cwxyz
// as calculated by CalcFE

   return;
}

void set14(xyz,xyz2,itarg)
COOSTRU *xyz;
COOSTRU *xyz2;
int itarg;
{
    int i,j,k,l,m,n,nn,i12,i13,i14;

    for (i=0; i<ndocka; i++) xyz->iaton[i] = 1;


    m = xyz2->iconn[itarg*(MXCON+1)];

    for (j=0; j < m; j++) {

	   i12 = xyz2->iconn[itarg*(MXCON+1)+1+j] - 1;
	   i12 = ABS(i12);

// switch off 1-2 van der Waals

	   xyz->iaton[i12] = 0;
	   n = xyz2->iconn[i12*(MXCON+1)];

	   for (k=0; k < n; k++) {

		i13 = xyz2->iconn[i12*(MXCON+1)+1+k] - 1;
		i13 = ABS(i13);

		if (i13 != itarg) {

// switch off 1-3 van der Waals

		   xyz->iaton[i13] = 0;
	   	   nn = xyz2->iconn[i13*(MXCON+1)];

	   	   for (l=0; l < nn; l++) {

			i14 = xyz2->iconn[i13*(MXCON+1)+1+l] - 1;
			i14 = ABS(i14);

			if (i14 != i12 && i14 != itarg) {
// mark 1-4 van der Waals
		   	   xyz->iaton[i14] = -1;
			}
		   }
		}
	   }
    }
}

void CalcFEL(COOSTRU *xyz, float *cool, float *ql,float *vdwrl,float *vdwel,
		float *F,float *E,float *dir)
{

// calculates van der waals (ev) and electrostatic energy (ev)
// of ligand with it self, The L in CalcFEL stands for ligand

   int i,j,k,l,ia2,ia3,n,m,ii,jj;
   float vr[3],rv,rv2,rs2,rs3,rsum,rinv,epsm,p6,p12,vscal;
   float de,e,ev,eq,econv,Fj[3];

   ev = 0.0; eq = 0.0;
   econv = 332.05382;

   vdwscal = vdwscal_memory;

   for (i=0; i < ndocka; i++) {

      set14(xyz,&DCKxyz,i);

      for (j=i+1; j < ndocka; j++) {

	 if (xyz->iaton[j]) {

		vscal = 1.0;
		if (xyz->iaton[j] == -1) vscal = 0.5;

		for (l=0; l < 3; l++) {
		   vr[l] = (cool[j*3+l] - cool[i*3+l]);
		   vr[l] = vr[l]*toangs;
		}

		rv2  = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];
		rv   = sqrt(rv2);
		rinv = 1.0/rv;
		rsum = vdwrl[i] + vdwrl[j];
		epsm = sqrt(vdwel[i]*vdwel[j]);
		epsm = epsm * vscal;
		rs2  = rsum*rsum;
		rs3  = rs2*rsum;
		p6   = (rs3*rs3) / (rv2*rv2*rv2);
		p12  = p6 * p6;

		e    = epsm * (p12 - 2.0*p6);
		de   = epsm * (p12 - p6) * (-12.0/rv);
		de   = de / rv;

		for (l=0; l < 3; l++) {
		   Fj[l] = de * vr[l];
		}

		ev   = ev + vdwscal*e;
  
		for (l=0; l < 3; l++) {
		   F[j*3+l] = F[j*3+l] + Fj[l];
		}

		e = ql[i]*ql[j]*econv*rinv*vscal;

		de = -e*rinv*rinv;

		for (l=0; l < 3; l++) {
		   F[j*3+l] = F[j*3+l] + de * vr[l];
		}

		eq = eq + e;	

	 }
      }
   }

   *E = eq + ev;

   for (j=0; j < ndocka; j++) {
	for (l=0; l < 3; l++) dir[l] = dir[l] + F[j*3+l];
   }

}

float Q_rsqrt( float number )
{
	long i;
	float x2, y;
	const float threehalfs = 1.5F;

	x2 = number * 0.5F;
	y  = number;
	i  = * ( long * ) &y;
	i  = 0x5f3759df - ( i >> 1 );
	y  = * ( float * ) &i;
	y  = y * ( threehalfs - ( x2 * y * y ) );

	return y;
}

void CalcFE(float *cool,double *coo,int *iclos,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel,
		float *F,float *E,float *dir,int *frg)
{
// Calculates interaction energy of protein with fragment of the ligand
// specified by frg[]                            

   int i,j,k,l;
   float vr[3],rv,rv2,rs2,rs3,rs6,rv6,rsum,rinv,epsm,p6,p12;
   float de,e,ev,eq,econv,Fj[3];

   ev = 0.0; eq = 0.0;
   econv = 332.05382;
   vdwscal = vdwscal_memory;

   for (j=0; j < ndocka; j++) {
     for (l=0; l < 3; l++) {
	F[j*3+l] = 0.0;
     }
   }


   for (i=0; i < *xyzp->iatoms; i++) {
     if (iclos[i]) {
	for (j=0; j < ndocka; j++) {
	 if (frg[j]) {
	   for (l=0; l < 3; l++) {
		vr[l] = (cool[j*3+l] - (float) coo[i*3+l]);
		vr[l] =  vr[l]*toangs;
	   }
	   rv2 = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];
	   rv = sqrt(rv2);
	   rinv = 1.0/rv;
	   rsum = vdwr[i] + vdwrl[j];
	   epsm = sqrt(vdwe[i]*vdwel[j]);
	   rs2 = rsum*rsum;
	   rs3 = rs2*rsum;
	   rs6 = rs3*rs3;
	   rv6 = rv2*rv2*rv2;
	   p6   = rs6 / rv6;
	   p12  = p6 * p6;

	   e    = epsm * (p12 - 2.0*p6);
	   de   = epsm * (p12 - p6) * (-12.0*rinv);
	   de   = de * rinv;

	   for (l=0; l < 3; l++) {
		Fj[l] = de * vr[l];
	   }

	   ev   = ev + vdwscal*e;
   
	   for (l=0; l < 3; l++) {
		F[j*3+l] = F[j*3+l] + Fj[l];
	   }

	   e = q[i]*ql[j]*econv*rinv;

	   de = -e*rinv*rinv;

	   for (l=0; l < 3; l++) {
		F[j*3+l] = F[j*3+l] + de * vr[l];
	   }

	   eq = eq + e;	
	 }
	}
     }
   }

   *E = eq + ev;

   for (l=0; l < 3; l++) dir[l] = 0.0;

   for (j=0; j < ndocka; j++) {
	for (l=0; l < 3; l++) dir[l] = dir[l] + F[j*3+l];
   }

}

void CaljFE(float *cool,double *coo,int *iclos,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel,
		float *F,float *E,float *dir,int *frg)
{

// calculates van der waals (ev) and electrostatic energy (eq)
// of protein (only atoms in iclos) with ligand (returns sum *E)

   int i,j,k,l;
   float vr[3],rv,rv2,rs2,rs3,rsum,rinv,epsm,p6,p12;
   float de,e,ev,eq,econv,Fj[3];

   ev = 0.0; eq = 0.0;
   econv = 332.05382;

   for (j=0; j < ndocka; j++) {
     for (l=0; l < 3; l++) {
	F[j*3+l] = 0.0;
     }
   }

   for (i=0; i < *xyzp->iatoms; i++) {
      if (((xyzp->iclos[i] == 1) && DCKMETH == 0) ||
	(iclos[i] && DCKMETH == 1)) {
	for (j=0; j < ndocka; j++) {
	   for (l=0; l < 3; l++) {
		vr[l] = (cool[j*3+l] - (float) coo[i*3+l]);
		vr[l] =  vr[l]*toangs;
	   }
	   rv2 = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];
	   rv = sqrt(rv2);
	   rinv = 1.0/rv;
	   rsum = vdwr[i] + vdwrl[j];
	   epsm = sqrt(vdwe[i]*vdwel[j]);
	   rs2 = rsum*rsum;
	   rs3 = rs2*rsum;
	   p6   = (rs3*rs3) / (rv2*rv2*rv2);
	   p12  = p6 * p6;

	   e    = epsm * (p12 - 2.0*p6);
	   de   = epsm * (p12 - p6) * (-12.0/rv);
	   de   = de / rv;

	   for (l=0; l < 3; l++) {
		Fj[l] = de * vr[l];
	   }

	   ev   = ev + e;
   
	   for (l=0; l < 3; l++) {
		F[j*3+l] = F[j*3+l] + Fj[l];
	   }

	   e = q[i]*ql[j]*econv*rinv;

	   de = -e*rinv*rinv;

	   for (l=0; l < 3; l++) {
		F[j*3+l] = F[j*3+l] + de * vr[l];
	   }

	   eq = eq + e;	
	}
     }
   }

   *E = eq + ev;

   for (l=0; l < 3; l++) dir[l] = 0.0;

   for (j=0; j < ndocka; j++) {
	for (l=0; l < 3; l++) dir[l] = dir[l] + F[j*3+l];
   }
}

float golden(float *cool,double *coo,int *iclos,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel,
		float *F,float a,float b,
		float *dir,int *frg)
{
//
// Golden section search
//
   float c,d,gr,tol,Ec,Ed,dum[3];
   float wxyz[3*MXLIGA];
   int i,j;

   gr = (sqrt(5.0) - 1.0) / 2.0;
   tol = 1.0e-5;

   c = a + (b - a)*(1.0-gr);
   d = a + (b - a)*gr;

   while (ABS(c-d) > tol) {

	for (i=0; i < ndocka; i++) {
	   for (j=0; j < 3; j++) {
		wxyz[3*i+j] = cool[3*i+j];
	   }
	}

	Newxyz(c,dir,wxyz);
	if (!FASTSLOW) {
		CalcFE(wxyz,coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&Ec,dum,frg);
	} else {
		CalcFE(wxyz,coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&Ec,dum,frg);
	}

	for (i=0; i < ndocka; i++) {
	   for (j=0; j < 3; j++) {
		wxyz[3*i+j] = cool[3*i+j];
	   }
	}

	Newxyz(d,dir,wxyz);
	if (!FASTSLOW) {
		CalcFE(wxyz,coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&Ed,dum,frg);
	} else {
		CalcFE(wxyz,coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&Ed,dum,frg);
	}
	if (Ec < Ed) {
	   b = d;
	   d = c;
	   c = a + (1.0-gr)*(b-a);
	} else {
	   a = c;
	   c = d;
	   d = a + gr*(b-a);
	}
   }

   for (i=0; i < ndocka; i++) {
	for (j=0; j < 3; j++) {
	    cool[3*i+j] = wxyz[3*i+j];
	}
   }

   return((b+a)/2.0);
}

void Rxyz(float xin, float yin, float zin, 
	  int a, int b, int c,
	  float *xout, float *yout, float *zout)
{
  float csa,sna,csb,snb,csc,snc;

  Get_FTsin(a,&sna,&csa);
  Get_FTsin(b,&snb,&csb);
  Get_FTsin(c,&snc,&csc);


  *xout = xin*csa*csb + yin*(csa*snb*snc - sna*csc) +
		        zin*(csa*snb*csc + sna*snc);
  *yout = xin*sna*csb + yin*(sna*snb*snc + csa*csc) +
		        zin*(sna*snb*csc - csa*snc);
  *zout = -xin*snb + yin*csb*snc + zin*csb*csc;
}

void Trans2Cen(float *coot, int itri, int ndocka)
{
// translate origin to center of triangle
   int i,j;

   for (i=0; i < ndocka; i++) {
	for (j=0; j < 3; j++) {
	   coot[3*i+j] = ((float) TriArr[itri]->coo[3*i+j] - 
				TriArr[itri]->Cen[j]);
	}
   }
}

void Cen2Trans(float *coot, int itri, int ndocka)
{
   int i,j;

   for (i=0; i < ndocka; i++) {
	for (j=0; j < 3; j++) {
	   coot[3*i+j] = (coot[3*i+j] + (float) TriArr[itri]->Cen[j]);
	}
   }
}

void PickFrags(int *indx, int itri, int ndocka)
{
   int i,j;

   for (i=0; i < ndocka; i++) {
	indx[i] = 0;
	if (singleb.ifrg[i] == TriArr[itri]->frags[0] ||
	    singleb.ifrg[i] == TriArr[itri]->frags[1] ||
	    singleb.ifrg[i] == TriArr[itri]->frags[2]) indx[i] = 1;
   }
}

void PickFrag(int *indx, int itri, int ndocka)
{
   int i,j;

   for (i=0; i < ndocka; i++) {
	indx[i] = 0;
	if (singleb.ifrg[i] == TriArr[itri]->frag) indx[i] = 1;
   }
}

void PickFull(int *indx, int ndocka)
{
   int i;

   for (i=0; i < ndocka; i++) indx[i] = 1;
}

int ChkFrag(int *indx,int ndocka)
{
   int i,j;

   for (i=0; i < ndocka; i++) {
	if (indx[i] == 1) return(1);
   }
   return(0);
}

int Write_Results(File_Name,Tri,ntri,xyz,Eopt,maxi)
char *File_Name;
TRISTRU *Tri[MAXTRI];
int ntri;
COOSTRU *xyz;
int Eopt;
int maxi;
{
   int ierr,i,l,n,iattmp,ipdbtmp,maxsol,itel;
   int *ianztmp;
   int *pppiconn, *ppplw, *ppplr;
   double *pppcoo,*pppqat;
   int *ityptmp;
   int len;

   len = strlen(File_Name);
   filclo_(&SEVENTYSEVEN);

   ierr = 0;
   openfil_(&SEVENTYSEVEN,File_Name,&len,&ONE,&ZERO,&ZERO,&ierr);

   if (!ierr) {
	fprintf(stderr,"WARNING: was not able to write docking output\n");
	return(0);
   }

if (debugdck) fprintf(stderr,"\nWrite_Results: %s\n\n",File_Name);

   ianztmp = xyzp->ianz;
   ityptmp = xyzp->ityp;
   pppiconn = xyzp->iconn;
   ppplw = xyzp->lwrit;
   ppplr = xyzp->lring;
   pppcoo = xyzp->coo;
   pppqat = xyzp->qat;
   xyzp->ianz = xyz->ianz;
   xyzp->ityp = DCKxyz.ityp;
   xyzp->lwrit = xyz->lwrit;
   xyzp->lring = xyz->lring;
   xyzp->iconn = xyz->iconn;

   iattmp = *xyzp->iatoms;
   *xyzp->iatoms = ndocka;
   ipdbtmp = *ipdbon;
   *ipdbon = 0;

   eneptr->iener = 1;

   if (maxi) {
	maxsol = dcksol;
	n = MINI(ntri,maxsol);
   } else {
	n = ntri;
   }

if (debugdck) fprintf(stderr,"Write_Results: n %d Eopt %d\n",n,Eopt);

   itel = 0;
   for (i = 0; i < n; i++ ) {
      if (Tri[i] != NULL && Tri[i]->coo != NULL) {

	eneptr->lig[0] = Tri[i]->lig[0];
	eneptr->lig[1] = Tri[i]->lig[1];
	eneptr->lig[2] = Tri[i]->lig[2];
	eneptr->prot[0] = Tri[i]->prot[0];
	eneptr->prot[1] = Tri[i]->prot[1];
	eneptr->prot[2] = Tri[i]->prot[2];
	eneptr->conf    = Tri[i]->conf;

	if (Eopt == 1) {
	   eneptr->energy = Tri[i]->eint;

	   if (!debugdck) {
		fprintf(stderr,"#%d E=%.3f\n",i,Tri[i]->eint);
	   } else {
		fprintf(stderr,"#%d E=%.3f lig %d %d %d prot %d %d %d d12 %.3f d13 %.3f d23 %.3f conf %d spec %d\n",i,Tri[i]->eint,Tri[i]->lig[0],Tri[i]->lig[1],Tri[i]->lig[2],Tri[i]->prot[0],Tri[i]->prot[1],Tri[i]->prot[2],Tri[i]->d12,Tri[i]->d13,Tri[i]->d23,Tri[i]->conf,Tri[i]->spec);
	   }
	} else if (Eopt == 3) {
	   eneptr->energy = Tri[i]->overl;

	   if (!debugdck) {
		fprintf(stderr,"#%d E=%.3f\n",i,Tri[i]->overl);
	   } else {
		fprintf(stderr,"#%d E=%.3f lig %d %d %d prot %d %d %d d12 %.3f d13 %.3f d23 %.3f conf %d\n",i,Tri[i]->overl,Tri[i]->lig[0],Tri[i]->lig[1],Tri[i]->lig[2],Tri[i]->prot[0],Tri[i]->prot[1],Tri[i]->prot[2],Tri[i]->d12,Tri[i]->d13,Tri[i]->d23,Tri[i]->conf);
	   }
	} else if (Eopt == 2) {
	   eneptr->energy = Tri[i]->e12;

	   if (!debugdck) {
		fprintf(stderr,"#%d E=%.3f\n",i,Tri[i]->e12);
	   } else {
		fprintf(stderr,"#%d E=%.3f lig %d %d %d prot %d %d %d d12 %.3f d13 %.3f d23 %.3f conf %d\n",i,Tri[i]->e12,Tri[i]->lig[0],Tri[i]->lig[1],Tri[i]->lig[2],Tri[i]->prot[0],Tri[i]->prot[1],Tri[i]->prot[2],Tri[i]->d12,Tri[i]->d13,Tri[i]->d23,Tri[i]->conf);
	   }
	} else {
	   eneptr->energy = Tri[i]->etot;

	   if (!debugdck) {
		fprintf(stderr,"#%d E=%.3f\n",i,Tri[i]->etot);
	   } else {
		fprintf(stderr,"#%d E=%.3f lig %d %d %d prot %d %d %d d12 %.3f d13 %.3f d23 %.3f\n",i,Tri[i]->etot,Tri[i]->lig[0],Tri[i]->lig[1],Tri[i]->lig[2],Tri[i]->prot[0],Tri[i]->prot[1],Tri[i]->prot[2],Tri[i]->d12,Tri[i]->d13,Tri[i]->d23);
	   }
	}

	wrmod_(&SEVENTYSEVEN,
	Tri[i]->coo,xyz->qat,xyz->ianz,xyz->iaton,xyz->iatclr,xyz->iconn,
	xyz->iresid,xyz->lring,DCKxyz.ityp,xyz->ipdbt,
	calfptr->icalf,&calfptr->ncalf,calfptr->iamino,&calfptr->ishoh);
	itel++;
      }
   }

   eneptr->iener = 0;
   *xyzp->iatoms = iattmp;
   *ipdbon = ipdbtmp;
   xyzp->ianz = ianztmp;
   xyzp->ityp = ityptmp;
   xyzp->iconn = pppiconn;
   xyzp->lwrit = ppplw;
   xyzp->lring = ppplr;
   xyzp->coo = pppcoo;
   xyzp->qat = pppqat;

   fprintf(stderr,"\n");

   filclo_(&SEVENTYSEVEN);

}

int Write_Mol(File_Name,nats,dckxyz,mode)
char *File_Name;
int nats;
COOSTRU dckxyz;
int mode;
{
   int ierr,i,n,iattmp,ipdbtmp,maxsol,itel;
   int *ianztmp, mxnatd;
   int *ityptmp;
   COOSTRU *pp;
   int idum;
   double rdum;
   double *pppcoo,*pppqat;
   int *pppianz, *pppiconn, *ppplw, *ppplr;
   int *pppityp;

   pppcoo = xyzp->coo;
   pppianz = xyzp->ianz;
   pppqat = xyzp->qat;
   pppiconn = xyzp->iconn;
   pppityp = xyzp->ityp;
   ppplw = xyzp->lwrit;
   ppplr = xyzp->lring;

   pp = xyzp;

   ierr = openfil_(&SEVENTYSEVEN,&ONE,&ZERO,&ZERO);

   if (ierr) {
      fprintf(stderr,"WARNING: was not able to write mol from ligand");
   }


   iattmp = *xyzp->iatoms;
   ipdbtmp = *ipdbon;
   mxnatd = *(xyzp->mxnat);

   *xyzp->iatoms = nats;
   *ipdbon = 0;

   xyzp->coo = dckxyz.coo;
   xyzp->ianz = dckxyz.ianz;
   xyzp->qat = dckxyz.qat;
   xyzp->iconn = dckxyz.iconn;
   xyzp->ityp = dckxyz.ityp;
   xyzp->lwrit = dckxyz.lwrit;
   xyzp->lring = dckxyz.lring;

   if (mode == 0) {
	outmod_(&SEVENTYSEVEN,
	dckxyz.coo,dckxyz.ianz,dckxyz.iconn);
   } else {
	wrmod_(&SEVENTYSEVEN,
	dckxyz.coo,dckxyz.qat,dckxyz.ianz,dckxyz.iaton,dckxyz.iatclr,
	dckxyz.iconn,
	dckxyz.iresid,dckxyz.lring,dckxyz.ityp,dckxyz.ipdbt,
	&idum,&ZERO,&idum,&idum,
	&idum,&idum,&idum, &rdum,&rdum,&rdum, &rdum,&rdum,&rdum);

   }

   xyzp->coo = pppcoo;
   xyzp->ianz = pppianz;
   xyzp->qat = pppqat;
   xyzp->iconn = pppiconn;
   xyzp->ityp = pppityp;
   xyzp->lwrit = ppplw;
   xyzp->lring = ppplr;

   *xyzp->iatoms = iattmp;
   *ipdbon = ipdbtmp;
   *(xyzp->mxnat)  = mxnatd;

   filclo_(&SEVENTYSEVEN);

}

void OHRotCoo(float *coo, double **oh, int i1, int i2, int i3, int it)
{

// i1 is C, i2 is O is Origin (O), i3 is H

   int i,j;
   float v1[3],v2[3],v3[3],O[3],XX,YY,arad;
   float v12[3],v32[3],cosa,sina,csa,sna,vl,todeg;

   todeg = 45.0e0/atan(1.0e0);

   if (!allConf(&oh[it],36)) exit(-1);

   for (j=0; j<3; j++) {
	O[j]   = coo[i2*3+j];
	v12[j] = coo[i1*3+j] - coo[i2*3+j];
	v32[j] = coo[i3*3+j] - coo[i2*3+j];
	v1[j]  = v12[j];
   }
   
   vecnrm(v1);
   cross(v1,v32,v3);
   vecnrm(v3);
   cross(v1,v3,v2);
   IMPRD(v32,v2,&cosa,1);
   IMPRD(v32,v1,&sina,1);
   vl = veclen(v32);

   XX = vl*cosa;
   YY = vl*sina;

   for (i=0; i<36; i++) {
	arad = (float) (i*10);
	csa = cos(arad/todeg);
	sna = sin(arad/todeg);
	
	for (j=0; j<3; j++) {
	   oh[it][i*3+j] = O[j] + XX*(csa*v2[j] + sna*v3[j]) + YY*v1[j];
	}

   }

}

void OHFndCoo(float *coo, double **oh,double *cooProt,int i3, int it)
{
   int i,j,iopt,indx;
   double dd,tt,ddmin;

   ddmin = BIGD;
   iopt = -1;

   for (i=0; i<36; i++) {
	dd = 0.0;
	for (j=0; j<3; j++) {
	   tt = cooProt[j] - oh[it][i*3+j];
	   tt =  tt * tt;
	   dd = dd + tt;
	}
	if (dd < ddmin) {
	   ddmin = dd;
	   iopt = i;
	}
   }

   if (iopt != -1) {

	for (j=0; j<3; j++) {
	   coo[i3*3+j] = oh[it][iopt*3+j];
	}
	
   }
}

void OHrealCoo(int itri,float *rwxyz)
{
   int j,i;
   double *oh[3];

   for (j=0; j<3; j++) {
     if (TriArr[itri]->ohlig[j] == 1) {
	i = TriArr[itri]->lig[j];
	OHRotCoo(rwxyz,oh,
		ligtyp[i]->atom[2],ligtyp[i]->atom[1],ligtyp[i]->atom[0],j);
	OHFndCoo(rwxyz,oh,
		inttyp[TriArr[itri]->prot[j]]->ORI,ligtyp[i]->atom[0],j);
     }
   }
}

int RetFrgNmb(int itri,int ligindx)
{
   int frgnmb;

   frgnmb = singleb.ifrg[ligtyp[TriArr[itri]->lig[ligindx]]->atom[0]];
   return(frgnmb);
}

void RotLine(int itri,float *line,  
		float *wxyz, float *rwxyz, float *cwxyz, 
		float *q, float *vdwr, float *vdwe,
		float *ql, float *vdwrl, float *vdwel, float *F,
		float *dir, int *frg, int *iclos)
{

   int i,k,l,j,frst,frgnmba,frgnmbb;
   float Emin,E,vl,c;
   int ang,angm,angle;
   float csa,sna;
   double R[4][4];
   float pt[3];
   TRISTRU *Tri[1];

   Emin = 1000000000.0;
   angm = 10000; 
   frst = 1;

   if (!TriArr[itri]->spec) Cen2Trans(wxyz,itri,ndocka);

   for (k=0; k < ndocka; k++) {
	for (l=0; l < 3; l++)  {
	   cwxyz[k*3+l] = (float) TriArr[itri]->coo[k*3+l];
	}
   }

   for (i=0; i < 4; i++) {
      for (j=0; j < 4; j++) {
        R[i][j] = 0.0;
      }
   }

   for (ang=0; ang < 36; ang++) {
		angle = ang*10.0;

		Get_FTsin(angle,&sna,&csa);
		Frst_Rot(TriArr[itri]->Cen,line,sna,csa,R);
		
		for (k=0; k < ndocka; k++) {

		    for (j=0; j < 3; j++) {
			pt[j] = (float) TriArr[itri]->coo[k*3+j];
		    }

		    xyzROT4(R,pt);

		    for (j=0; j<3; j++) {
			rwxyz[k*3+j] = pt[j];
		    }
		}

		OHrealCoo(itri,rwxyz);

// calculate forces and energy on rotated ligand coordinates

		if (!FASTSLOW) {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		} else {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		}

		if (E < Emin)  {
		    Emin = E;
		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++)  {
			   cwxyz[k*3+l] = rwxyz[k*3+l];
			}
		    }
		    angm = ang;
		}

   } 


   for (ang=angm-10; ang < angm+10; ang++) {

		Get_FTsin(ang,&sna,&csa);
		Frst_Rot(TriArr[itri]->Cen,line,sna,csa,R);
		
		for (k=0; k < ndocka; k++) {

		    for (j=0; j < 3; j++) {
			pt[j] = (float) TriArr[itri]->coo[k*3+j];
		    }

		    xyzROT4(R,pt);

		    for (j=0; j<3; j++) {
			rwxyz[k*3+j] = pt[j];
		    }
		}


// calculate forces and energy on rotated ligand coordinates

		if (!FASTSLOW) {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		} else {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		}

		if (E < Emin)  {
		    Emin = E;
		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++)  {
			   cwxyz[k*3+l] = rwxyz[k*3+l];
			}
		    }
		    angm = ang;
		}

   } 
//   if (Emin < 50.0) {
//   if (Emin < 60000.0) {
   if (Emin < 200000.0) {

	TriArr[itri]->eint = Emin;

	for (k=0; k < ndocka; k++) {
	   for (l=0; l < 3; l++) {
		TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
	   }
	}

//	if (TriArr[itri]->spec && TriArr[itri]->oneline) {
	if (TriArr[itri]->spec) {
	   frgnmba = RetFrgNmb(itri,0);
	   frgnmbb = RetFrgNmb(itri,1);

	   for (i=0; i < ndocka; i++) {
		frg[i] = 0;
		if (frgnmba == singleb.ifrg[i] || 
			frgnmbb == singleb.ifrg[i]) {
	   	   frg[i] = 1;
		}
	   }
	}

	if (!FASTSLOW) {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	} else {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	}

	vl = veclen(dir); if (vl == 0.0) return;

	for (l=0; l < 3; l++) dir[l] = -dir[l] / vl;

	c = golden(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,0.0,1.0,dir,frg);

	if (!FASTSLOW) {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	} else {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	}

fprintf(stderr,"spec %d oneline %d\n",TriArr[itri]->spec,TriArr[itri]->oneline);
//	if (TriArr[itri]->spec && TriArr[itri]->oneline) {
	if (TriArr[itri]->spec) {

	   vl = veclen(dir); if (vl == 0.0) return;

	   for (l=0; l < 3; l++) dir[l] = -dir[l] / vl;

	   c = golden(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,0.0,1.0,dir,frg);

	   if (!FASTSLOW) {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	   } else {
		CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	   }

	   vl = veclen(dir); if (vl == 0.0) return;

	   for (l=0; l < 3; l++) dir[l] = -dir[l] / vl;

	   c = golden(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,0.0,1.0,dir,frg);

	   PickFull(frg,ndocka);

	   for (k=0; k < 2; k++) {

		if (!FASTSLOW) {
			CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		} else {
			CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		}

		vl = veclen(dir); if (vl == 0.0) return;

		for (l=0; l < 3; l++) dir[l] = -dir[l] / vl;

		c = golden(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,0.0,1.0,dir,frg);

           }

	   if (!FASTSLOW) {
			CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	   } else {
			CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
	   }

	}

	if (E < 0.0) {

	   TriArr[itri]->eint = E;

	   for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++) {
		   TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
		}
	   }
		   
	} else {
	   TriArr[itri]->eint = 0.0;

	   for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++) {
		   TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
		}
	   }
		   
	}
   } else {
	   for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++) {
		   TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
		}
	   }
   }

   eint_calculated = 1;
}

typedef struct {float E; int ind;} CMPSTR;

int fcmp(const void * p1, const void * p2)
{
        CMPSTR *q1 = (CMPSTR *) p1;
        CMPSTR *q2 = (CMPSTR *) p2;

	if (q1->E > q2->E)
		return 1;

	if (q1->E < q2->E)
		return -1;
	else
		return 0;
}

#define ADCUT 3.00

int GetSpec(int i, float *cooTriAD0,float *cooTriAD1)
{
   CMPSTR estru[3];
   int j;

   for (j=0; j < 3; j++) {
	estru[j].E = TriArr[i]->e12c[j];
	estru[j].ind = j;
   }

   qsort(estru,3,sizeof(CMPSTR),fcmp);

   if (fabs(estru[0].E + estru[1].E)/2.0 - fabs(estru[2].E) > ADCUT) {
	if (estru[0].ind == 0) {
	   for (j=0; j < 3; j++) {
		cooTriAD0[j] = TriArr[i]->p1[j];
	   }
	} else if (estru[0].ind == 1) {
	   for (j=0; j < 3; j++) {
		cooTriAD0[j] = TriArr[i]->p2[j];
	   }
	} else if (estru[0].ind == 2) {
	   for (j=0; j < 3; j++) {
		cooTriAD0[j] = TriArr[i]->p3[j];
	   }
	}

	if (estru[1].ind == 0) {
	   for (j=0; j < 3; j++) {
		cooTriAD1[j] = TriArr[i]->p1[j];
	   }
	} else if (estru[1].ind == 1) {
	   for (j=0; j < 3; j++) {
		cooTriAD1[j] = TriArr[i]->p2[j];
	   }
	} else if (estru[1].ind == 2) {
	   for (j=0; j < 3; j++) {
		cooTriAD1[j] = TriArr[i]->p3[j];
	   }
	}
	return(1);
   } else {
      return(0);
   }
}

void CalcRVec(i,Vec)
int i;
float *Vec;
{
   int j,k,l,spec,type[3],typtot,iset;
   float V1[4];
   float cooTriAD0[3],cooTriAD1[3];

   spec = 0; type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
   iset = -1;

/* check for 2x H_DON/H_ACC + 1 != H_DON/H_ACC */


   if (TriArr[i]->spec) {
	CalcOne_Spec(i);
   } else {
	CalcOne(i);
   }

   for (j = 0; j<3; j++ ) {
	if (ligtyp[TriArr[i]->lig[j]]->type == H_ACC ||
		ligtyp[TriArr[i]->lig[j]]->type == H_DON) {
		type[j] = 1;
		if (iset == -1) {
		   if (j == 0) {
			cooTriAD0[0] = TriArr[i]->p1[0];
			cooTriAD0[1] = TriArr[i]->p1[1];
			cooTriAD0[2] = TriArr[i]->p1[2];
		   } else if (j == 1) {
			cooTriAD0[0] = TriArr[i]->p2[0];
			cooTriAD0[1] = TriArr[i]->p2[1];
			cooTriAD0[2] = TriArr[i]->p2[2];
		   } else if (j == 2) {
			cooTriAD0[0] = TriArr[i]->p3[0];
			cooTriAD0[1] = TriArr[i]->p3[1];
			cooTriAD0[2] = TriArr[i]->p3[2];
		   }
		   iset = 1;
		} else {
		   if (iset == 1) {
		   	if (j == 0) {
			   cooTriAD1[0] = TriArr[i]->p1[0];
			   cooTriAD1[1] = TriArr[i]->p1[1];
			   cooTriAD1[2] = TriArr[i]->p1[2];
		   	} else if (j == 1) {
			   cooTriAD1[0] = TriArr[i]->p2[0];
			   cooTriAD1[1] = TriArr[i]->p2[1];
			   cooTriAD1[2] = TriArr[i]->p2[2];
		   	} else if (j == 2) {
			   cooTriAD1[0] = TriArr[i]->p3[0];
			   cooTriAD1[1] = TriArr[i]->p3[1];
			   cooTriAD1[2] = TriArr[i]->p3[2];
		   	}
			iset = 2;
		   }
		}
	} else {
		type[j] = 0;
	}
	typtot = typtot + type[j];
   }

   if (typtot == 2) spec = 1;

   if (spec == 0) {
      if (typtot == 3) {
	   spec = GetSpec(i,cooTriAD0,cooTriAD1);
      }
   }

   if (spec) {
	for (j = 0; j<3; j++ ) {
	   TriArr[i]->Cen[j] = (cooTriAD0[j] + cooTriAD1[j])/2.0;
	   Vec[j] = cooTriAD0[j] - TriArr[i]->Cen[j];
	}
	vecnrm(Vec);
   } else {
	Vec[0] = 1.0; Vec[1] = 0.0; Vec[2] = 0.0; Vec[3] = 0.0;
	vecnrm(Vec);
   }

}

void RotTri(int itri, int lowa, int higha, int angstp, 
		float *wxyz, float *rwxyz, float *cwxyz, 
		float *q, float *vdwr, float *vdwe,
		float *ql, float *vdwrl, float *vdwel, float *F,
		float *dir, int *frg, int *iclos)
{
// lowa -4 hiang  5 angstp 1.0 BmpCheck 1 ECheck 1
// lowa -9 hiang 10 angstp 5.0 BmpCheck 0 ECheck 0

   int k,l,j;
   float Emin,E,vl,tdir[3],c;
   int angx,angy,angz,angxm,angym,angzm;
   int anglex,angley,anglez;

   Emin = 10000.0;
   angxm = 10000; angym = 10000; angzm = 10000;

// translate origin to center of triangle


   Trans2Cen(wxyz,itri,ndocka);

///* loop over a,b,c angles to calculate Energy as function of angles */

   for (angx=lowa; angx < higha; angx++) {
	anglex = angx*angstp;

	for (angy=lowa; angy < higha; angy++) {
	    angley = angy*angstp;

	    for (angz=lowa; angz < higha; angz++) {
		anglez = angz*angstp;

// do rotation around x,y,x axes (Rx,Ry,Rz) and copy to rwxyz

		for (k=0; k < ndocka; k++) {
		    Rxyz(wxyz[k*3], wxyz[k*3+1], wxyz[k*3+2], 
			anglex,angley,anglez,
			&rwxyz[k*3], &rwxyz[k*3+1], &rwxyz[k*3+2]);
		}

		Cen2Trans(rwxyz,itri,ndocka);

		OHrealCoo(itri,rwxyz);

// calculate forces and energy on rotated ligand coordinates

	        if (!FASTSLOW) {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		} else {
			CalcFE(rwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,&E,dir,frg);
		}

		if (E < Emin)  {
		    Emin = E;
		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++)  {
			   cwxyz[k*3+l] = rwxyz[k*3+l];
			}
		    }
		    angxm = angx;
		    angym = angy;
		    angzm = angz;
		}

	    } // end for anglez
	} // end for angley
   } // end for anglex

if (debugdck) fprintf(stderr,"RotTri Emin %.3f\n",Emin);

   if (Emin < 50.0) {
//   if (Emin < BIGD) {

	TriArr[itri]->eint = Emin;

	for (k=0; k < ndocka; k++) {
	   for (l=0; l < 3; l++) {
		TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
	   }
	}

	if (!FASTSLOW) {
	   CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	} else {
	   CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	}

	vl = veclen(dir); if (vl == 0.0) return;

	for (l=0; l < 3; l++) dir[l] = -dir[l] / vl;

	c = golden(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,0.0,1.0,dir,frg);

	if (!FASTSLOW) {
	   CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	} else {
	   CalcFE(cwxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	}

if (debugdck) fprintf(stderr,"RotTri E %.3f\n",E);

	if (E < 0.0) {
//	if (E < 100.0) {

	   TriArr[itri]->eint = E;

	   for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++) {
		   TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
		}
	   }

	   for (l=0; l < 3; l++) {
		tdir[l] = (cwxyz[l] - rwxyz[l]);
		TriArr[itri]->Cen[l] = TriArr[itri]->Cen[l] + (double) tdir[l];
	   }

	} else {
	   TriArr[itri]->eint = 0.0;
	}
   }

   eint_calculated = 1;

}

int struct_cmp(const AREASTRU * lhs, const AREASTRU * rhs)
{
    return memcmp(lhs, rhs, sizeof(AREASTRU));
}

void OHFnd(TRISTRU *Tri,double *cooProt,int it)
{
   int i,j,iopt,indx,il;
   double dd,tt,ddmin;

   ddmin = BIGD;
   iopt = -1;

   for (i=0; i<36; i++) {
	dd = 0.0;
	for (j=0; j<3; j++) {
	   tt = cooProt[j] - Tri->oh[it][i*3+j];
	   tt =  tt * tt;
	   dd = dd + tt;
	}
	if (dd < ddmin) {
	   ddmin = dd;
	   iopt = i;
	}
   }

   if (iopt != -1) {

	indx = Tri->lig[it];
	il = ligtyp[indx]->atom[0];

	for (j=0; j<3; j++) {
	   Tri->coo[il*3+j] = Tri->oh[it][iopt*3+j];
	}
	
   }
}

void OHAllInt(C,indx,at1,at2,at3,at4,coo,ohcoo,iconf,link,ohsame,jj)
COOSTRU *C;
int *indx;
int at1;
int at2;
int at3;
int at4;
double *coo;
double *ohcoo;
int iconf;
int link;
int ohsame;
int jj;
{
   int j;
   float aret;
   int asel[4];
   INCRSTRU tmptyp;
   double cbck[3];

   ligtyp[*indx] =  (INCRSTRU *) malloc((sizeof tmptyp));
   memcpy(ligtyp[*indx],&IncrIni,sizeof(INCRSTRU));

   for (j=0; j<3; j++) {
	ligtyp[*indx]->ORI[j]  = ohcoo[jj*3+j];
	ligtyp[*indx]->c[0][j] = ohcoo[jj*3+j];
	ligtyp[*indx]->c[1][j] = coo[(at2)*3+j];
	ligtyp[*indx]->c[2][j] = coo[(at3)*3+j];
   }

   ligtyp[*indx]->atom[0] = at1;
   ligtyp[*indx]->atom[1] = at2;
   ligtyp[*indx]->atom[2] = at3;
   ligtyp[*indx]->atom[3] = at4;
   ligtyp[*indx]->n = 2;

   ligtyp[*indx]->type = H_DON;
   ligtyp[*indx]->area = ONH;
   ligtyp[*indx]->conf = iconf;
   ligtyp[*indx]->link = link;
   ligtyp[*indx]->ohlig = 1;
   ligtyp[*indx]->ohsame = ohsame;

   for (j=0; j<3; j++) {
      cbck[j] = coo[(at1)*3+j];
      coo[(at1)*3+j] = ohcoo[jj*3+j];
   }

   asel[0] = at1+1;
   asel[1] = at2+1;
   asel[2] = at3+1;
   asel[3] = at4+1;

   tomold_(&aret,asel,&FOUR);

   for (j=0; j<3; j++) {
      coo[(at1)*3+j] = cbck[j];
   }

   ligtyp[*indx]->dih = (double) aret;

   cal_area(ligtyp[*indx]);

   (*indx)++;
}

void OHGRot(double *coo, int i1, int i2, int i3,int iang)
{

// i1 is C, i2 is O is Origin (O), i3 is H

   int i,j;
   float v1[3],v2[3],v3[3],O[3],XX,YY,arad;
   float v12[3],v32[3],cosa,sina,csa,sna,vl,todeg;
   double GenOH[3];

   todeg = 45.0e0/atan(1.0e0);

   for (j=0; j<3; j++) {
	O[j]   = (float) (coo[i2*3+j]);
	v12[j] = (float) (coo[i1*3+j] - coo[i2*3+j]);
	v32[j] = (float) (coo[i3*3+j] - coo[i2*3+j]);
	v1[j]  = v12[j];
   }
   
   vecnrm(v1);
   cross(v1,v32,v3);
   vecnrm(v3);
   cross(v1,v3,v2);
   IMPRD(v32,v2,&cosa,1);
   IMPRD(v32,v1,&sina,1);
   vl = veclen(v32);

   XX = vl*cosa;
   YY = vl*sina;

   arad = (float) (iang);
   csa = cos(arad/todeg);
   sna = sin(arad/todeg);
	
   for (j=0; j<3; j++) {
	GenOH[j] = (double) (O[j] + XX*(csa*v2[j] + sna*v3[j]) + YY*v1[j]);
   }

   for (i=0; i<3; i++) {
       coo[i3*3+i] = GenOH[i];
   }
}

void OHGenRot(double *coo, double **GenOH, int i1, int i2, int i3,
		int n, int iang)
{

// i1 is C, i2 is O is Origin (O), i3 is H

   int i,j;
   float v1[3],v2[3],v3[3],O[3],XX,YY,arad;
   float v12[3],v32[3],cosa,sina,csa,sna,vl,todeg;
   double *OHPTR;

   todeg = 45.0e0/atan(1.0e0);

   if (!allConf(GenOH,n)) exit(-1);
   
   OHPTR = *GenOH;

   for (j=0; j<3; j++) {
	O[j]   = (float) (coo[i2*3+j]);
	v12[j] = (float) (coo[i1*3+j] - coo[i2*3+j]);
	v32[j] = (float) (coo[i3*3+j] - coo[i2*3+j]);
	v1[j]  = v12[j];
   }
   
   vecnrm(v1);
   cross(v1,v32,v3);
   vecnrm(v3);
   cross(v1,v3,v2);
   IMPRD(v32,v2,&cosa,1);
   IMPRD(v32,v1,&sina,1);
   vl = veclen(v32);

   XX = vl*cosa;
   YY = vl*sina;

   for (i=0; i<n; i++) {
	arad = (float) (i*iang);
	csa = cos(arad/todeg);
	sna = sin(arad/todeg);
	
	for (j=0; j<3; j++) {
	   OHPTR[i*3+j] = (float) (O[j] + XX*(csa*v2[j] + sna*v3[j]) + YY*v1[j]);
	}

   }

}

void OHRot(TRISTRU *Tri, int i1, int i2, int i3, int it)
{

// i1 is C, i2 is O is Origin (O), i3 is H

   int i,j;
   float v1[3],v2[3],v3[3],O[3],XX,YY,arad;
   float v12[3],v32[3],cosa,sina,csa,sna,vl,todeg;

   todeg = 45.0e0/atan(1.0e0);

   if (!allConf(&Tri->oh[it],36)) exit(-1);

   for (j=0; j<3; j++) {
	O[j]   = (float) (Tri->coo[i2*3+j]);
	v12[j] = (float) (Tri->coo[i1*3+j] - Tri->coo[i2*3+j]);
	v32[j] = (float) (Tri->coo[i3*3+j] - Tri->coo[i2*3+j]);
	v1[j]  = v12[j];
   }
   
   vecnrm(v1);
   cross(v1,v32,v3);
   vecnrm(v3);
   cross(v1,v3,v2);
   IMPRD(v32,v2,&cosa,1);
   IMPRD(v32,v1,&sina,1);
   vl = veclen(v32);

   XX = vl*cosa;
   YY = vl*sina;

   for (i=0; i<36; i++) {
	arad = (float) (i*10);
	csa = cos(arad/todeg);
	sna = sin(arad/todeg);
	
	for (j=0; j<3; j++) {
	   Tri->oh[it][i*3+j] = O[j] + XX*(csa*v2[j] + sna*v3[j]) + YY*v1[j];
	}

   }

}

static int cmpd(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria) == NULL || (*Trib) == NULL) return -1;
    if ((*Tria)->dcnt > (*Trib)->dcnt) return 1;
    else
       if ((*Tria)->dcnt == (*Trib)->dcnt) return  0;
       else          return -1;
}

static int cmpeint(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria) == NULL || (*Trib) == NULL) return -1;
    if ((*Tria)->eint > (*Trib)->eint) return 1;
    else
       if ((*Tria)->eint == (*Trib)->eint) return  0;
       else          return -1;
}

static int cmpe12(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria) == NULL || (*Trib) == NULL) return -1;
    if ((*Tria)->e12 > (*Trib)->e12) return 1;
    else
       if ((*Tria)->e12 == (*Trib)->e12) return  0;
       else          return -1;
}

static int cmpover(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria) == NULL || (*Trib) == NULL) return -1;
    if ((*Tria)->overl > (*Trib)->overl) return 1;
    else
       if ((*Tria)->overl == (*Trib)->overl) return  0;
       else          return -1;
}

static int cmptriF(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria)->etot > (*Trib)->etot) return 1;
    else {
       if ((*Tria)->etot == (*Trib)->etot) return  0;
       else          return -1;
    }
}

int Match_Tri(TRISSTRU Tri,int l1,int l2,int l3)
{

    if (Tri.lig[0] == l1 &&
	Tri.lig[1] == l2 &&
	Tri.lig[2] == l3 ) {
	return(1);
   }

return(0);

}

int Match_tri(TRISTRU * Tri,int l1,int l2,int l3,int p1,int p2,int p3)
{

if (Tri->lig[0] == l1 &&
    Tri->lig[1] == l2 &&
    Tri->lig[2] == l3 ) {
    if (Tri->prot[0] == p1 &&
	Tri->prot[1] == p2 &&
	Tri->prot[2] == p3 ) {
	return(1);
   }
}

return(0);

}

#define MXFRG 20000

void Get_Att_Frag(int ifrag,int *FrgArr,int *FrgN)
{
   int i;

   for (i=0; i < singleb.N; i++) {
	if (singleb.SngFrg[i][0] == ifrag || singleb.SngFrg[i][1] == ifrag) {
	   if (*FrgN < MXFRG) {
	      if (singleb.SngFrg[i][0] == ifrag) {
		FrgArr[*FrgN] = singleb.SngFrg[i][1];
	      }
	      if (singleb.SngFrg[i][1] == ifrag) {
		FrgArr[*FrgN] = singleb.SngFrg[i][0];
	      }
	      (*FrgN)++;
	   }
	}
   }
}

void R2Tri(float *v1, float *cen, float *wxyz, int dg, int itri)
{
   int i,j,deg;
   float pt[3],CEN[3];
   double R1[4][4],sina,cosa;

   Get_Tsin(dg,&sina,&cosa);

   CEN[0] = 0.0; CEN[1] = 0.0; CEN[2] = 0.0;

   vecnrm(v1);

   Frst_Rot(CEN,v1,sina,cosa,R1);

   for (i=0; i<ndocka; i++) {


     for (j=0; j < 3; j++) {
	wxyz[3*i+j] = ((float) TriArr[itri]->coo[3*i+j] - cen[j]);
     }


     for (j=0; j<3; j++) {
	pt[j] = wxyz[i*3+j];
     }

     xyzROT4(R1,pt);

     for (j=0; j<3; j++) {
	wxyz[i*3+j] = pt[j] + cen[j];
     }

   }

}


void TriRot(int itri, float *wxyz, float *cwxyz, float *cen, float *v1,
		float *q, float *vdwr, float *vdwe,
		float *ql, float *vdwrl, float *vdwel, float *F,
		float *dir, int *frg, int *iclos)
{

   int k,l;
   float Emin,E,tdir[3];
   int ang;
   float angle;

   Emin = BIGD;

// translate origin to center of triangle

   for (ang=-60; ang < 61; ang++) {

	R2Tri(v1,cen,wxyz,ang,itri);

// calculate forces and energy on rotated ligand coordinates

	if (!FASTSLOW) {
	   CalcFE(wxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	} else {
	   CalcFE(wxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	}

	if (E < Emin)  {
	    Emin = E;
	    for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++)  {
		   cwxyz[k*3+l] = wxyz[k*3+l];
		}
	    }
	}

   } 

   if (Emin < BIGD) {

	TriArr[itri]->eint = Emin;

	for (k=0; k < ndocka; k++) {
	    for (l=0; l < 3; l++) {
		TriArr[itri]->coo[k*3+l] = (double) cwxyz[k*3+l];
	    }
	}
		   
   } else {
	TriArr[itri]->eint = 0.0;
   }


   eint_calculated = 1;
}

int GenCen(int itri,float *v,float *cen)
{
   int i,j,ind1,ind2,lig[3],itel;
   double co[3][3];

   itel = 0;

   for (i=0; i < 3; i++) {
	lig[i] = TriArr[itri]->lig[i];

	if (ligtyp[lig[i]]->type == H_ACC) {

	   for (j=0; j < 3; j++) {
		co[itel][j] = TriArr[itri]->coo[3*ligtyp[lig[i]]->atom[0]+j];
	   }
	   itel++;

	} else if (ligtyp[lig[i]]->type == H_DON) {

	   for (j=0; j < 3; j++) {
		co[itel][j] = TriArr[itri]->coo[3*ligtyp[lig[i]]->atom[1]+j];
	   }
	   itel++;
	}
   }
   
   if (itel == 2) {
      for (j=0; j < 3; j++) {
	v[j] = co[1][j] - co[0][j];
	cen[j] = (co[1][j] + co[0][j])/2.0;
      }
      return(1);
   } else {
      return(0);
   }
}

int IsAccDon(int itri)
{
   int i,lig[3],typ[3],ida[3];

   if (itri < 0) return(0);

   for (i=0; i < 3; i++) {
	ida[i] = 0;
	if (TriArr[itri] != NULL) {
	   lig[i] = TriArr[itri]->lig[i];
	   typ[i] = ligtyp[lig[i]]->type;
	   if (typ[i] == H_ACC || typ[i] == H_DON) ida[i] = 1;
	}
   }

   if (ida[0] && ida[1] && ida[2]) return(1);

   return(0);
}

void ConvertSectoDay(int n)
{
    int day = (int) n / (24.0 * 3600.0);
  
    n = n % (24 * 3600);
    int hour = n / 3600;
  
    n %= 3600;
    int minutes = n / 60 ;
  
    n %= 60;
    int seconds = n;
      
    fprintf(stderr,"days %d hours %d minutes %d seconds %d\n",
		    day,hour,minutes,seconds);
}

void DIMPRD(double *a, double *b, double *c,int norm)
{
      int i;
      double rimp, al, bl;

      rimp = 0.0;

      for (i=0; i<3; i++) rimp = rimp + a[i]*b[i];

      al = dveclen(a);
      bl = dveclen(b);

      if (al > 0.0 && bl > 0.0) {
         if (norm) {
            *c = rimp / (al*bl);
         } else {
            *c = rimp;
         }
      } else {
         *c = 0.0;
      }

}

void normalize(v)     
double *v;
{
   double d;

   d = sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); 

   if (d != 0.0) {

	v[0] /= d; v[1] /= d; v[2] /= d; 

   }

}

void crossp(a,b,d)
double *a;
double *b;
double *d;
{
/*

       calculates cross product:  (v1) x (v2) = d
                                   ---     ---    -
       This routine was created because the old
       'crossprd' was giving the vector with the wrong sign
*/
      int i;
      double dlen;

      d[0] =  a[1]*b[2]-a[2]*b[1];
      d[1] = -a[0]*b[2]+a[2]*b[0];
      d[2] =  a[0]*b[1]-a[1]*b[0];
      dlen = sqrt(d[0]*d[0]+d[1]*d[1]+d[2]*d[2]);

      if (dlen > 0 ) for (i=0; i<3; i++) d[i] = d[i] / dlen;
}

int ClockWise(v1,v2,v3)
double v1[3];
double v2[3];
double v3[3];
{
  double tmp1[3],tmp2[3],tmp3[3],out[3];
  int ret;

  ret = 0;

  normalize(v1);
  normalize(v2);
  normalize(v3);

  crossp(v1,v2,tmp1);
  normalize(tmp1);
  DIMPRD(tmp1,v3,&out[0],1);

fprintf(stderr,"ClockWise v1xv2 tmp %7.3f %7.3f %7.3f v3 %7.3f %7.3f %7.3f out %7.3f\n",tmp1[0],tmp1[1],tmp1[2],v3[0],v3[1],v3[2],out[0]);

  crossp(v2,v3,tmp2);
  normalize(tmp2);
  DIMPRD(tmp2,v1,&out[1],1);

fprintf(stderr,"ClockWise v2xv3 tmp %7.3f %7.3f %7.3f v1 %7.3f %7.3f %7.3f out %7.3f\n",tmp2[0],tmp2[1],tmp2[2],v1[0],v1[1],v1[2],out[1]);

  crossp(v3,v1,tmp3);
  normalize(tmp3);
  DIMPRD(tmp3,v2,&out[2],1);

fprintf(stderr,"ClockWise v3xv1 tmp %7.3f %7.3f %7.3f v2 %7.3f %7.3f %7.3f out %7.3f\n",tmp3[0],tmp3[1],tmp3[2],v2[0],v2[1],v2[2],out[2]);

  if (out[0] > 0.5) {
fprintf(stderr,"clockwise basis\n");
	ret = 1;
  } else {
fprintf(stderr,"anti clockwise basis\n");
	ret = 0;
	return(ret);
  }

  if (out[1] > 0.5) {
fprintf(stderr,"clockwise basis\n");
	ret = 1;
  } else {
fprintf(stderr,"anti clockwise basis\n");
	ret = 0;
	return(ret);
  }

  if (out[2] > 0.5) {
	ret = 1;
fprintf(stderr,"clockwise basis\n");
  } else {
fprintf(stderr,"anti clockwise basis\n");
	ret = 0;
	return(ret);
  }

  return(ret);
}

#define NLOWCUTOFF -15.0
//#define OPTTRISCUTOFF 600
#define OPTTRISCUTOFF 3500
static int OPTCUT = -1;

void OriONH(car,nar,lig0,lig1,lig2,prot0,prot1,prot2)
double car[3];
double nar[3];
int lig0;
int lig1;
int lig2;
int prot0;
int prot1;
int prot2;
{
  double t[3],v1[3],v2[3],v3[3],vn[3],vx[3],NAR[3],CAR[3],HAR[3],nup[3];
  double sina,cosa,tmp[3],hlp[3];
  double d0,d1,d2;
  double try[3];
  int size,i,j,k,it,*iclos;
  TRISTRU *Tri[1];
  float *F,E;
  float *q,*vdwr,*vdwe,dir[3],tdir[3];
  float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
  int frg[MXLIGA];
  float *wxyz;

  allConf(&Tri1.coo,ndocka);
  size = MXLIGA;

  Tri[0] = &Tri1;

  if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

  allFConf(&wxyz,ndocka);

  AssChg(q);
  AssVDW(vdwr,vdwe);
  AssVDWL(vdwrl,vdwel,ql);

  TriAll(&TriArr[ntris]);
  TriArr[ntris]->coo = (double *) malloc(sizeof(double)*ndocka*3);
  TriArr[ntris]->lig[0] = lig0;
  TriArr[ntris]->lig[1] = lig1;
  TriArr[ntris]->lig[2] = lig2;
  TriArr[ntris]->prot[0] = prot0;
  TriArr[ntris]->prot[1] = prot1;
  TriArr[ntris]->prot[2] = prot2;
  TriArr[ntris]->conf = 0;

// Perhaps take other conformations
// NAR is the newly predicted position of the ONH partner of the CO
// CAR is the newly predicted position of the CO  partner of the NHP

  for (j=0; j<3; j++) {
	NAR[j] = DCKxyz.coo[ligtyp[TriArr[ntris]->lig[0]]->atom[1]*3+j];
	CAR[j] = DCKxyz.coo[ligtyp[TriArr[ntris]->lig[1]]->atom[1]*3+j];
  }

  vsubd(car,nar,v1);  normalize(v1);
  vsubd(CAR,NAR,vn);  normalize(vn);
  crossp(v1,vn,v3); normalize(v3);
  crossp(v3,v1,v2); normalize(v2);

  vsubd(nar,NAR,t);

  DIMPRD(v1,vn,&cosa,1);
  DIMPRD(v2,vn,&sina,1);

fprintf(stderr,"1st cosa %7.3f sina %7.3f\n",cosa,sina);

//  ClockWise(v1,v2,v3);

// apply translation to nar[3]

  if (TriFin[0] == NULL) return;

  for (i=0; i < ndocka; i++) {
     for (j=0; j<3; j++) {
	TriArr[ntris]->coo[i*3+j] = TriFin[0]->coo[i*3+j] + t[j];
	Tri1.coo[i*3+j] = TriFin[0]->coo[i*3+j] + t[j];
	hlp[j] = TriFin[0]->coo[i*3+j] + t[j];
	tmp[j] = hlp[j];
     }
     vsubd(hlp,nar,tmp);

// should both vecs be normalized ? IMPRD works on float vecs
// and devides the dot product by both lenght of both vecs
// see RotDih()

     DIMPRD(tmp,v1,&d0,0);
     DIMPRD(tmp,v2,&d1,0);
     DIMPRD(tmp,v3,&d2,0);

     for (j=0; j<3; j++) {
    	tmp[j] =  nar[j] +
		 ( cosa*d0 + sina*d1)*v1[j] + 
		 (-sina*d0 + cosa*d1)*v2[j] + 
		  d2*v3[j];
	Tri1.coo[i*3+j] = tmp[j];
	TriArr[ntris]->coo[i*3+j] = tmp[j];
     }
  }

// nar[3] is still the old coordinate, we have to update it !

  for (j=0; j<3; j++) {
	CAR[j] = xyzp->coo[inttyp[TriArr[ntris]->prot[0]]->atom[0]*3+j];
        HAR[j] = TriArr[ntris]->coo[ligtyp[TriArr[ntris]->lig[0]]->atom[0]*3+j];
	nar[j] = TriArr[ntris]->coo[ligtyp[TriArr[ntris]->lig[0]]->atom[1]*3+j];
  }

// CAR is now the C=O of glutamin 453
// HAR is Hydrogen attached to NAR
// vn = NH --- NAR
// v1 = O=C --- NAR
// v3 = vnxv1
// v2 = v1xv3

  vsubd(CAR,nar,v1);  normalize(v1);
  vsubd(HAR,nar,vn);  normalize(vn);
  crossp(v1,vn,v3); normalize(v3);
  crossp(v3,v1,v2); normalize(v2);

  DIMPRD(v1,vn,&cosa,1);
  DIMPRD(v2,vn,&sina,1);

fprintf(stderr,"2nd cosa %7.3f sina %7.3f\n",cosa,sina);

//  ClockWise(v1,v2,v3);

  for (i=0; i < ndocka; i++) {
     for (j=0; j<3; j++) {
	hlp[j] = TriArr[ntris]->coo[i*3+j];
	tmp[j] = hlp[j];
     }
     vsubd(hlp,nar,tmp);

     DIMPRD(tmp,v1,&d0,0);
     DIMPRD(tmp,v2,&d1,0);
     DIMPRD(tmp,v3,&d2,0);

     for (j=0; j<3; j++) {
    	tmp[j] =  nar[j] +
		 ( cosa*d0 + sina*d1)*v1[j] + 
		 (-sina*d0 + cosa*d1)*v2[j] + 
		  d2*v3[j];
	Tri1.coo[i*3+j] = tmp[j];
	TriArr[ntris]->coo[i*3+j] = tmp[j];
     }
  }

  for (j=0; j<3; j++) {
	NAR[j] = TriArr[ntris]->coo[ligtyp[TriArr[ntris]->lig[0]]->atom[1]*3+j];
	CAR[j] = TriArr[ntris]->coo[ligtyp[TriArr[ntris]->lig[1]]->atom[1]*3+j];
  }

  vsubd(CAR,NAR,v1);  normalize(v1);
  vsubd(car,nar,vn);  normalize(vn);
  crossp(v1,vn,v3); normalize(v3);
  crossp(v3,v1,v2); normalize(v2);

  DIMPRD(v1,vn,&cosa,1);
  DIMPRD(v2,vn,&sina,1);

fprintf(stderr,"3th cosa %7.3f sina %7.3f\n",cosa,sina);

//  ClockWise(v1,v2,v3);

  for (i=0; i < ndocka; i++) {
     for (j=0; j<3; j++) {
	hlp[j] = TriArr[ntris]->coo[i*3+j];
	tmp[j] = hlp[j];
     }
     vsubd(hlp,nar,tmp);

     DIMPRD(tmp,v1,&d0,0);
     DIMPRD(tmp,v2,&d1,0);
     DIMPRD(tmp,v3,&d2,0);

     for (j=0; j<3; j++) {
    	tmp[j] =  nar[j] +
		 ( cosa*d0 - sina*d1)*v1[j] + 
		 ( sina*d0 + cosa*d1)*v2[j] + 
		  d2*v3[j];
	Tri1.coo[i*3+j] = tmp[j];
	TriArr[ntris]->coo[i*3+j] = tmp[j];
     }
  }

  FillOptD(iclos);
  PickFull(frg,ndocka);

  for (k=0; k < ndocka; k++) {
	for (j=0; j < 3; j++) {
	   wxyz[3*k+j] = (float) TriArr[ntris]->coo[3*k+j];
	}
  }

// all we need is a realistic xyzp->coo, that is just the loaded protein

  CalcFE(wxyz,xyzp->coo,iclos,q,vdwr,vdwe,
	ql,vdwrl,vdwel,F,&E,dir,frg);

  TriArr[ntris]->eint = E;
  eint_calculated = 1;

  ntris++;
}

void identify(lig0,lig1,lig2,prot0,prot1,prot2)
int lig0;
int lig1;
int lig2;
int prot0;
int prot1;
int prot2;
{
   double car[3],nar[3];

   if (debugdck) {
	fprintf(stderr,"identify\n");
   }

   if (lig0 >= lintp || lig1 >= lintp || lig2 >= lintp) return;
//                                 NHP                               CO
   if ((ligtyp[lig0]->area.iden == 3) && (ligtyp[lig1]->area.iden == 1)) {
//                                       CO,ONH
	if ((inttyp[prot0]->area.iden == 1) 		
		&& (inttyp[prot1]->area.iden == 2)) {
	   double c[3],d[3];
	   int i;

	   for (i=0; i<3; i++) {
// N (NHP) with C (C)=O : Ligand
		c[i] = ligtyp[lig0]->c[0][i] - ligtyp[lig1]->c[1][i];
// C (C)=O with N (ONH) : Protein
		d[i] = inttyp[prot0]->c[1][i] - inttyp[prot1]->c[0][i];
	   }

	   if (dveclen(c)*toangs < 3.0 && dveclen(d)*toangs < 3.0) {
			INVESTIGATE = 1;

// CD,OE2,NE2
                        CreateNPos(&xyzp->coo[inttyp[prot0]->atom[1]*3],
                                   &xyzp->coo[inttyp[prot0]->atom[0]*3],
                                   &xyzp->coo[inttyp[prot1]->atom[1]*3],
                                   nar);
fprintf(stderr,"nar coordinates %7.3f %7.3f %7.3f\n",	
		nar[0]*toangs,nar[1]*toangs,nar[2]*toangs);
// NE2,HE2,CD
                        CreateCPos(&xyzp->coo[inttyp[prot1]->atom[1]*3],
                                   &xyzp->coo[inttyp[prot1]->atom[0]*3],
                                   &xyzp->coo[inttyp[prot0]->atom[1]*3],
                                   car);
fprintf(stderr,"car coordinates %7.3f %7.3f %7.3f\n",	
		car[0]*toangs,car[1]*toangs,car[2]*toangs);

			OriONH(car,nar,lig0,lig1,lig2,prot0,prot1,prot2);


	   }
	}
   }
}

void DelTriNOT(lig0,lig1,lig2,prot0,prot1,prot2,conf)
int lig0;
int lig1;
int lig2;
int prot0;
int prot1;
int prot2;
int conf;
{
    int i;

    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {

	if (Match_tri(TriArr[i],lig0,lig1,lig2,prot0,prot1,prot2)) {
	   if (TriArr[i]->conf != conf) {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"CalcSchInt_Spec_3k3e",		
		"Reason: only entries lig 20 14 0 prot 151 150 160 conf 0");
	   }
	} else {
	   TriCooSafeFree(i);
	   TriSafeFreeTxt(i,"CalcSchInt_Spec_3k3e",		
		"Reason: only entries lig 20 14 0 prot 151 150 160 conf 0");
        }
      }
    }

    Compress_Tri_L();

//    ntris = 20;
}

int FilterTris()
{
   int i,j,k,l,n,it,*iclos,bumps,fnd;
   float *F,E,a,b,c,vl;
   float *q,*vdwr,*vdwe,dir[3],tdir[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int frg[MXLIGA],nlow,ncut;
   float *wxyz,*rwxyz,*cwxyz,*tmpxyz,cen[3],vrot[3],Ebck,Vec[4];
   time_t curtime;
   float eintlow;
   int ieint,secs;
   double secnds;

   eintlow = BIGD;
   ieint = -1;
   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return(0);

   allFConf(&wxyz,ndocka);
   allFConf(&rwxyz,ndocka);
   allFConf(&cwxyz,ndocka);
   allFConf(&tmpxyz,ndocka);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   if (ntris > 0) {
	if (IsAccDon(0)) {
	   vdwscal = VDWSCAL;
	}
	if (!MapConformers) vdwscal = VDWSCAL;
   }

   vdwscal_memory = vdwscal;

   bumps = 0;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    if (ChkBump(iclos,i,0)) bumps++;
	}
   }

   if (bumps > ntris/2) {
	fprintf(stderr,"Lowering van der Waals scaling to 0.01 to alleviate bump(s)\n");
	VDWSCAL = 0.01;
   }

   nlow = 0;
   ncut = -1;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    TriArr[i]->dorot = 0;
	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    if (TriArr[i]->spec != 2 && TriArr[i]->spec != 3) ChkBump(iclos,i,1);

// translate origin to center of triangle

	    Trans2Cen(wxyz,i,ndocka);

	    PickFull(frg,ndocka);

	    if (TriArr[i]->spec == 1) {
		CalcRVec(i,Vec);
		RotLine(i,Vec,  
		wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,dir,frg,iclos);
	    } else {
	    	RotTri(i,-2,3,15,
			wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);
	    }

	    if (TriArr[i]->eint <= 0.0) {

	      if (!TriArr[i]->spec) {
		if (GenCen(i,vrot,cen)) {

		   Ebck = TriArr[i]->eint;

		   FillFull(iclos,i);

		   PickFull(frg,ndocka);

		   TriRot(i,wxyz,cwxyz,cen,vrot,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);

		   TriArr[i]->eint = Ebck;
		}
	      }

	      if (TriArr[i]->eint < eintlow) {
		  eintlow = TriArr[i]->eint;
		  ieint = i;
	      }

	      if (TriArr[i]->eint < NLOWCUTOFF) nlow++;

//	      if (i > OPTTRISCUTOFF && nlow >= 5) {
	      if (i > OPTCUT && nlow >= 5) {
		ncut = i + 1;
		break;
	      }


	    } else {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"FilterTris","Reason: Eint > 0");
	    }

	}
   }

   Compress_Tri_L();

   if (ncut != -1) {
	for (i=ncut; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"FilterTris 2","Reason: Eint > 0");
	   }
	}
	ntris = ncut;
   }

   Compress_Tri_L();

//   if (strcmp(pdbcode,"3k3e") == 0) DelTriNOT(20,14,0,151,150,160,0);

   if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
   }

   vdwscal = 1.0;

   if (ieint != -1) {
       TriArr[ieint]->dorot = 1;
   }

   eint_calculated = 1;

if (debugdck) Write_Results("filtdock.mol2",TriArr,ntris,&DCKxyz,1,0);

   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"FilterTris took:\n\n");
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}

int FilterTris_Spec()
{
   int i,j,k,l,n,it,*iclos,bumps,fnd,OPTTRISC,ligselp;
   float *F,E,a,b,c,vl;
   float *q,*vdwr,*vdwe,dir[3],tdir[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int frg[MXLIGA],nlow,ncut;
   float *wxyz,*rwxyz,*cwxyz,*tmpxyz,cen[3],vrot[3],Ebck,Vec[4];
   time_t curtime;
   float eintlow;
   int ieint;

   eintlow = BIGD;
   ieint = -1;
   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return(0);

   allFConf(&wxyz,ndocka);
   allFConf(&rwxyz,ndocka);
   allFConf(&cwxyz,ndocka);
   allFConf(&tmpxyz,ndocka);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   if (ntris > 0) {
	if (IsAccDon(0)) {
	   vdwscal = VDWSCAL;
	}
	if (!MapConformers) vdwscal = VDWSCAL;
   }

   vdwscal_memory = vdwscal;

   bumps = 0;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    if (ChkBump(iclos,i,0)) bumps++;
	}
   }

   if (bumps > ntris/2) {
	fprintf(stderr,"Lowering van der Waals scaling to 0.01 to alleviate bump(s)\n");
	VDWSCAL = 0.01;
   }

   OPTTRISC = OPTCUT;
   ligselp = LigSel - 1;

   if ((strcmp(pdbcode,"3k3e") == 0)
	&& strcmp(hetptr.HetAtm[ligselp],"PDB") == 0) {
	OPTTRISC = 6000;
	fprintf(stderr,"Changed the default OPTTRISCUTOFF %d to %d\n",
		OPTCUT,OPTTRISC);
   }
   if ((strcmp(pdbcode,"1a28") == 0) 
	&& strcmp(hetptr.HetAtm[ligselp],"STR") == 0) {
 	ntris = 6000;
   }


   nlow = 0;
   ncut = -1;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    TriArr[i]->dorot = 0;
	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    if (TriArr[i]->spec != 2 && TriArr[i]->spec != 3) ChkBump(iclos,i,1);

// translate origin to center of triangle

	    PickFull(frg,ndocka);

	    if (TriArr[i]->spec == 1) {
		CalcRVec(i,Vec);
		RotLine(i,Vec,  
		wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,dir,frg,iclos);
	    } else {
	        Trans2Cen(wxyz,i,ndocka);
	    	RotTri(i,-2,3,15,
			wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);
	    }

	    if (TriArr[i]->eint <= 0.0) {

	      if (!TriArr[i]->spec) {
		if (GenCen(i,vrot,cen)) {

		   Ebck = TriArr[i]->eint;

		   FillFull(iclos,i);

		   PickFull(frg,ndocka);

		   TriRot(i,wxyz,cwxyz,cen,vrot,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);

		   TriArr[i]->eint = Ebck;
		}
	      }

	      if (TriArr[i]->eint < eintlow) {
		  eintlow = TriArr[i]->eint;
		  ieint = i;
	      }

	      if (TriArr[i]->eint < NLOWCUTOFF) nlow++;


	      if (i > OPTTRISC && nlow >= 5) {
		ncut = i + 1;
		break;
	      }


	    } else {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"FilterTris","Reason: Eint > 0");
	    }

	}
   }

   Compress_Tri_L();

   if (ncut != -1) {
	for (i=ncut; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"FilterTris 2","Reason: Eint > 0");
	   }
	}
	ntris = ncut;
   }

   Compress_Tri_L();

   if (ntris > 0) {
	if (MapConformers) {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	} else {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	}
   }

   vdwscal = 1.0;

   if (ieint != -1) {
       TriArr[ieint]->dorot = 1;
   }

   eint_calculated = 1;

if (debugdck) Write_Results("filtdock.mol2",TriArr,ntris,&DCKxyz,1,0);

}

#define E12WIN 7.5

int OptTris()
{
   int i,j,k,l,n,it,*iclos,bumps,Etype,secs,ligselp;
   float *F,E,a,b,c,vl;
   float Elowint,Elowtot;
   float *q,*vdwr,*vdwe,dir[3],tdir[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int frg[MXLIGA];
   float *wxyz,*rwxyz,*cwxyz,*tmpxyz,cen[3],vrot[3],Ebck,Vec[4];
   time_t curtime;
   double secnds;

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return(0);

   allFConf(&wxyz,ndocka);
   allFConf(&rwxyz,ndocka);
   allFConf(&cwxyz,ndocka);
   allFConf(&tmpxyz,ndocka);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   ligselp = LigSel - 1;

   if (eint_calculated) {
	for (i=0;i < ntris;i++) {
	   if (TriArr[i] != NULL) {
		if (TriArr[i]->coo != NULL) {
		   if (TriArr[i]->eint >= 0.0) {
			TriArr[i] = NULL;
		   }
		}
	   }
	}
	Compress_Tri_L();

   }

   if (ntris > 0) {
	if (IsAccDon(0)) {
	   vdwscal = VDWSCAL;
	}
	if (!MapConformers) vdwscal = VDWSCAL;
   }

if (debugdck)  {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"begin OptTris: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}

   bumps = 0;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    if (ChkBump(iclos,i,0)) bumps++;
	}
   }

   if (bumps > ntris/2) {
	fprintf(stderr,"Lowering van der Waals scaling to 0.01 to alleviate bump(s)\n");
	VDWSCAL = 0.01;
   }

   if (strcmp(pdbcode,"4isi") == 0
	&& strcmp(hetptr.HetAtm[ligselp],"1GG") == 0) {
	ntris = 100;
   }

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    FillOpt(iclos,i);

	    ChkBump(iclos,i,1);

// translate origin to center of triangle

	    Trans2Cen(wxyz,i,ndocka);

	    if (MapConformers) {
		if (TriArr[i]->small) {
		   PickFull(frg,ndocka);
		} else {
		   PickFrag(frg,i,ndocka);
		   PickFull(frg,ndocka);
		}
	    } else {
		PickFrags(frg,i,ndocka);
		   PickFull(frg,ndocka);
	    }


	    if (TriArr[i]->spec == 1) {
		CalcRVec(i,Vec);
		RotLine(i,Vec,  
		wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,dir,frg,iclos);
	    } else {
	    	RotTri(i,-9,10,5,
			wxyz,rwxyz,cwxyz,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);
	    }

	    if (TriArr[i]->eint < 0.0) {

	      if (!TriArr[i]->spec) {
		if (GenCen(i,vrot,cen)) {

		   Ebck = TriArr[i]->eint;

		   FillFull(iclos,i);

		   PickFull(frg,ndocka);

		   TriRot(i,wxyz,cwxyz,cen,vrot,q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,dir,frg,iclos);

		   TriArr[i]->eint = Ebck;
		}
	      }

	    } else {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"OptTris","Reason: eint > 0");
	    }

	}
   }

   if (ntris > 0) {
	Etype = 0;
	if (MapConformers) {
	   if (eint_calculated) {
	      qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	      Etype = 1;
	   } else {
	      qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptriF);
	      Etype = 2;
	   }
	} else {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	   Etype = 1;
	}

	Elowint = BIGD;
	Elowtot = BIGD;
	for (i=0; i < 10; i++) {
    	   if (TriArr[i] != NULL) {
		if (TriArr[i]->eint < Elowint) {	
		   Elowint = TriArr[i]->eint;
		}
		if (TriArr[i]->eint < Elowtot) {	
		   Elowtot = TriArr[i]->etot;
		}
	   }
	}

	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
		if (TriArr[i]->coo != NULL) {
		   if (Etype == 1) {
    		     if (Elowint != BIGD) {
			if (TriArr[i]->eint > Elowint + E12WIN) {
			   TriArr[i] = NULL;
			}
		     }
		   } else if (Etype == 2) {
    		     if (Elowtot != BIGD) {
			if (TriArr[i]->etot > Elowtot + E12WIN) {
			   TriArr[i] = NULL;
			}
		     }
		   }
		}
	   }
	}

	Compress_Tri_L();
   }

   eint_calculated = 1;
   vdwscal = 1.0;

if (debugdck)  {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"end OptTris: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
   Write_Results("optdock.mol2",TriArr,ntris,&DCKxyz,1,0);
}

}

int gttpar(iat,it,trs1,trs2,trs3,trs4,ityp)
int iat[4];
int it[4];
float trs1[4];
float trs2[4];
float trs3[4];
float trs4[4];
int *ityp;
{
      float todeg,angl;
      int first = 1,i1,i2,i3,i4,ita,itb,itc,itd;
      int l,istat,it1,it2,it3,it4;

      todeg = 45.0e0 / atan(1.0e0);
      istat = 0;

      i1 = (int) ityp[iat[0]];
      i2 = (int) ityp[iat[1]];
      i3 = (int) ityp[iat[2]];
      i4 = (int) ityp[iat[3]];

      it[0] = iat[0];
      it[1] = iat[1];
      it[2] = iat[2];
      it[3] = iat[3];

      ita = ABS(i1);
      if (ita == 72) ita = 6;

      itb = ABS(i2);
      if (itb == 72) itb = 6;

      itc = ABS(i3);
      if (itc == 72) itc = 6;

      itd = ABS(i4);
      if (itd == 72) itd = 6;

      it1 = ita;
      it2 = itb;
      it3 = itc;
      it4 = itd;

      if (itb < itc) {
         it1 = ita;
         it2 = itb;
         it3 = itc;
         it4 = itd;
      } else if (itc < itb) {
         it1 = itd;
         it2 = itc;
         it3 = itb;
         it4 = ita;
      } else if (ita < itd) {
         it1 = ita;
         it2 = itb;
         it3 = itc;
         it4 = itd;
      } else if (itd < ita) {
         it1 = itd;
         it2 = itc;
         it3 = itb;
         it4 = ita;
      }

next:

      istat = 0;
      for (l=0;l<MXGTOR;l++) {
          if ((gftcon[l][0] == it1) &&
	      (gftcon[l][1] == it2) &&
	      (gftcon[l][2] == it3) &&
	      (gftcon[l][3] == it4) ) {

                 istat = 1;

                 trs1[0] = gftor1[l][0];
                 trs1[1] = gftor1[l][1];
                 angl = gftor1[l][1] / todeg;
                 trs1[2] = cos(angl);
                 trs1[3] = sin(angl);

                 trs2[0] = gftor2[l][0];
                 trs2[1] = gftor2[l][1];
                 angl = gftor2[l][1] / todeg;
                 trs2[2] = cos(angl);
                 trs2[3] = sin(angl);

                 trs3[0] = gftor3[l][0];
                 trs3[1] = gftor3[l][1];
                 angl = gftor3[l][1] / todeg;
                 trs3[2] = cos(angl);
                 trs3[3] = sin(angl);

                 trs4[0] = gftor4[l][0];
                 trs4[1] = gftor4[l][1];
                 angl = gftor4[l][1] / todeg;
                 trs4[2] = cos(angl);
                 trs4[3] = sin(angl);

	  }
      }

      if (istat == 0 && first) {
	it1 = 1;
	it4 = 1;
	first = 0;
	goto next;
      }

      if (istat == 0) 
            fprintf(stderr,"No torsion parameter: %3d %3d %3d %3d\n",\
		it[0],it[1],it[2],it[3]);

      return(istat);
}

// torset initialises torsion parameters, based on two atoms
// calls gttpar: gets parameters from gftor1,2,3,4 arrays
// based on connectivity of atom types (gftcon array)
// sets it[4] array
//
// first call torset then tors for calc etors (with it[4] as input)
// based on value of torsion angle, calculated from coordinates
//
// tors calculates Etors or Eimp_tors, depending on value idoimp

int torset(ia1,ia2,nt,it,trs1,trs2,trs3,trs4,iconn,ityp)
int ia1;
int ia2;
int *nt;
int it[MXTORS][4];
float trs1[MXTORS][4];
float trs2[MXTORS][4];
float trs3[MXTORS][4];
float trs4[MXTORS][4];
int *iconn;
int *ityp;
{
      int iat[4],i,j,k,l,itt[4];
      float trs1t[4],trs2t[4],trs3t[4],trs4t[4];

      iat[1] = ia1;
      iat[2] = ia2;
      *nt = 0;

      for (j=0; j < iconn[iat[1]*(MXCON+1)]; j++) {

	iat[0] = iconn[iat[1]*(MXCON+1)+1+j] - 1;

	if (iat[0] >= 0 && iat[0] != iat[2]) {

	   for (k=0; k < iconn[iat[2]*(MXCON+1)]; k++) {
		iat[3] = iconn[iat[2]*(MXCON+1)+1+k] - 1;

		if (iat[3] >= 0 && (iat[3] != iat[1] && iat[3] != iat[0]) ) {

		   if (gttpar(iat,itt,trs1t,trs2t,trs3t,trs4t,ityp)) {
			if (*nt < MXTORS) {
			   for (l=0; l < 4; l++) {
				it  [*nt][l] = itt[l];
				trs1[*nt][l] = trs1t[l];
				trs2[*nt][l] = trs2t[l];
				trs3[*nt][l] = trs3t[l];
				trs4[*nt][l] = trs4t[l];
			   }
			   (*nt)++;
			}
		   } else {
		      fprintf(stderr,"torsion parameter not found\n");
		      return(0);
		   }

		}

	   }

	}

      }

      return(1);
}

void tors(et,nt,it,trs1,trs2,trs3,trs4,coo)
float *et;
int nt;
int it[MXTORS][4];
float trs1[MXTORS][4];
float trs2[MXTORS][4];
float trs3[MXTORS][4];
float trs4[MXTORS][4];
double *coo;
// double coo or float coo ? check with dckxyz
// inprod outputs a double *, here used as float *; need conversion !!!
{

   int i,j,ia,ib,ic,id,nterms;
   float cosna[4],sinna[4],v[4],sa[4],ca[4],phi[4];
   float va[3],vb[3],vc[3],vd[3],vba[3],vcb[3],vdc[3],vca[3],vdb[3];
   float vt[3],vu[3],vtu[3];
   float rt2,ru2,rtru,rcb,e;

   *et = 0.0;

// ia,ib,ic,id should run from 0-n, and therfor so should iti[] and it[]

   nterms = 4;

   for (i=0; i < nt; i++) {

      ia = it[i][0];
      ib = it[i][1];
      ic = it[i][2];
      id = it[i][3];

// coordinates of atoms a,b,c,d

      for (j=0; j <3; j++) {
	va[j] = ((float) coo[ia*3+j])*toangs;
	vb[j] = ((float) coo[ib*3+j])*toangs;
	vc[j] = ((float) coo[ic*3+j])*toangs;
	vd[j] = ((float) coo[id*3+j])*toangs;
      }

// vectors ba, cb, dc, ca, db

      vsubt(vb,va,vba);
      vsubt(vc,vb,vcb);
      vsubt(vd,vc,vdc);
      vsubt(vc,va,vca);
      vsubt(vd,vb,vdb);

// t outvector ba x cb, u outvector cb x dc

      cross(vba,vcb,vt);
      cross(vcb,vdc,vu);

// tu outvector t x u

      cross(vt,vu,vtu);

      rt2 = vt[0]*vt[0] + vt[1]*vt[1] + vt[2]*vt[2];
      ru2 = vu[0]*vu[0] + vu[1]*vu[1] + vu[2]*vu[2];

      rtru = veclen(vu)*veclen(vt);

      if (rtru > 0.0) {

	rcb = veclen(vcb);

	IMPRD(vt,vu,&cosna[0],1);
	IMPRD(vcb,vtu,&sinna[0],0);

	sinna[0] = sinna[0] / (rcb*rtru);

// torsional parameters 

	v [0] = trs1[i][0];
	ca[0] = trs1[i][2];
	sa[0] = trs1[i][3];

	v [1] = trs2[i][0];
	ca[1] = trs2[i][2];
	sa[1] = trs2[i][3];

	v [2] = trs3[i][0];
	ca[2] = trs3[i][2];
	sa[2] = trs3[i][3];

	v [3] = trs4[i][0];
	ca[3] = trs4[i][2];
	sa[3] = trs4[i][3];


	for (j=0; j < nterms-1; j++) {
	   cosna[j+1] = cosna[0]*cosna[j] - sinna[0]*sinna[j];
	   sinna[j+1] = cosna[0]*sinna[j] + sinna[0]*cosna[j];
	}

	e = 0.0;

	for (j=0; j < nterms; j++) {
	   phi[j]  = 1.0 + (cosna[j]*ca[j] + sinna[j]*sa[j]);
	   e = e + v[j]*phi[j];
	}

	*et = *et + e;

      }
   }

}

float CalTorS(isng,xyz,coo,nt,it,trs1,trs2,trs3,trs4)
int isng;
COOSTRU *xyz;
double *coo;
int *nt;
int it[MXTORS][4];
float trs1[MXTORS][4];
float trs2[MXTORS][4];
float trs3[MXTORS][4];
float trs4[MXTORS][4];
{
   int i,j,ia1,ia2,err;
   float et;

   ia1 = singleb.sng[isng][0];
   ia2 = singleb.sng[isng][1];
   et = 0.0;err = 1;

   if (!singleb.sngdone[isng]) {
	err = torset(ia1,ia2,nt,it,trs1,trs2,trs3,trs4,
		xyz->iconn,singleb.ityp);
	singleb.sngnt[isng] = *nt;
	singleb.sngdone[isng] = 1;
	for (i=0; i < *nt; i++) {
	   for (j=0; j < 4; j++) {
		singleb.it[isng][i][j] = it[i][j];
		singleb.trs1[isng][i][j] = trs1[i][j];
		singleb.trs2[isng][i][j] = trs2[i][j];
		singleb.trs3[isng][i][j] = trs3[i][j];
		singleb.trs4[isng][i][j] = trs4[i][j];
	   }
	}
   } else {
	*nt = singleb.sngnt[isng];
	for (i=0; i < *nt; i++) {
	   for (j=0; j < 4; j++) {
		it[i][j]   = singleb.it[isng][i][j];
		trs1[i][j] = singleb.trs1[isng][i][j];
		trs2[i][j] = singleb.trs2[isng][i][j];
		trs3[i][j] = singleb.trs3[isng][i][j];
		trs4[i][j] = singleb.trs4[isng][i][j];
	   }
	}
   }

   if (err) tors(&et,*nt,it,trs1,trs2,trs3,trs4,coo);

   return et;
}

void vdwlj(ev,xyz)
float *ev;
COOSTRU *xyz;
{
      int i,j,k,i1,i2;
      float vr[3],v14sc,vdwr1,vdwr2,vdwe1,vdwe2,rv2,rsum,epsm,rv,
		rs2,rs3,p6,p12,e;

      *ev = 0.0;
      v14sc = 0.5;

// we only do this for 1..4 interactions

      for (i=0; i<ndocka; i++) {

	i1 = (int) xyz->ityp[i];
	i1 = ABS(i1)-1;
	vdwr1 = gfvdw[i1][0];
        vdwe1 = gfvdw[i1][1];

	if (vdwe1 != 0.0) {

	   for (k=i+1; k<ndocka; k++) {

		i2 = (int) xyz->ityp[k];
		i2 = ABS(i2)-1;
		vdwr2 = gfvdw[i2][0];
        	vdwe2 = gfvdw[i2][1];

		if (vdwe2 != 0.0) {

		  for (j=0; j<3; j++) {
			vr[j] = (xyz->coo[i*3+j] - xyz->coo[k*3+j])*toangs;
		  }
 
		  rv2 = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];


//          [ (Rmin)**12       (Rmin)**6 ]
// e = eps  [ (----)     - 2.0 (----)    ]
//          [ ( r  )           ( r  )    ]


		  rsum = vdwr1 + vdwr2;
		  epsm = sqrt(vdwe1 * vdwe2);
		  epsm = epsm * v14sc;
		  rv   = sqrt(rv2);
		  rs2  = rsum*rsum;
		  rs3  = rs2*rsum;
		  p6   = (rs3*rs3) / (rv2*rv2*rv2);
		  p12  = p6 * p6;

		  e    = epsm * (p12 - 2.0*p6);

		  *ev   = *ev + e;
   
		}

	   }
	}
      }

}

float vdwS(isng,xyz,coo)
int isng;
COOSTRU *xyz;
double *coo;
{
      int i,j,k,i1,i2,ia1,ia2,ia3,ia4;
      float vr[3],v14sc,vdwr1,vdwr2,vdwe1,vdwe2,rv2,rsum,epsm,rv,
		rs2,rs3,p6,p12,e,ev;

      ev = 0.0;
      v14sc = 0.5;

      ia1 = singleb.sng[isng][0];
      ia2 = singleb.sng[isng][1];

// we only do this for 1..4 interactions

      for (i=0; i < xyz->iconn[ia1*(MXCON+1)]; i++) {

	ia3 = xyz->iconn[ia1*(MXCON+1)+1+i] - 1;

	if (ia3 != ia2) {

	   i1 = (int) xyz->ityp[ia3];
	   i1 = ABS(i1)-1;
	   vdwr1 = gfvdw[i1][0];
           vdwe1 = gfvdw[i1][1];

	   if (vdwe1 != 0.0) {

	     for (k=0; k < xyz->iconn[ia2*(MXCON+1)]; k++) {

		ia4 = xyz->iconn[ia2*(MXCON+1)+1+k] - 1;

		if (ia4 != ia1) {

		   i2 = (int) xyz->ityp[ia4];
		   i2 = ABS(i2)-1;
		   vdwr2 = gfvdw[i2][0];
        	   vdwe2 = gfvdw[i2][1];

		   if (vdwe2 != 0.0) {

			for (j=0; j<3; j++) {
			   vr[j] = (coo[ia3*3+j] - coo[ia4*3+j])*toangs;
			}
 
			rv2 = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];


//          [ (Rmin)**12       (Rmin)**6 ]
// e = eps  [ (----)     - 2.0 (----)    ]
//          [ ( r  )           ( r  )    ]


			rsum = vdwr1 + vdwr2;
			epsm = sqrt(vdwe1 * vdwe2);
			epsm = epsm * v14sc;
			rv   = sqrt(rv2);
			rs2  = rsum*rsum;
			rs3  = rs2*rsum;
			p6   = (rs3*rs3) / (rv2*rv2*rv2);
			p12  = p6 * p6;

			e    = epsm * (p12 - 2.0*p6);

			ev   = ev + e;
   
		   }
		}

	     } // for k
	   } // ifend vdwe1 != 0
	} // ifend ia3 != ia2
      }

      return(ev);
}

void Create_Vecs(ia1,ia2,v1,v2,v3,k,xyz)
int ia1;
int ia2;
float *v1;
float *v2;
float *v3;
int k;
COOSTRU *xyz;
{
    int i,j,ia3;
    float vl,v23[3];

    for (j=0; j < 3; j++) {
	v1[j] = ((float) (TriArr[k]->coo[ia1*3+j] - 
			TriArr[k]->coo[ia2*3+j]));
    }

    vl = veclen(v1);

    for (j=0; j < 3; j++) {
	v1[j] = v1[j] / vl;
    }

    for (i=0; i < xyz->iconn[ia2*(MXCON+1)]; i++) {

	   ia3 = xyz->iconn[ia2*(MXCON+1)+1+i] - 1;

	   if (ia3 != ia1) {

		for (j=0; j < 3; j++) {
		   v23[j] = ((float) (TriArr[k]->coo[ia3*3+j] - 
		   		   TriArr[k]->coo[ia2*3+j]));
		}
		break;
	   }

    }

    cross(v1,v23,v2);

    vl = veclen(v2);

    for (j=0; j < 3; j++) {
	v2[j] = v2[j] / vl;
    }

    cross(v1,v2,v3);

}


void RotDih(ia1,ia2,euc,coo,feuc,angle,v1,v2,v3,idx)
int ia1;
int ia2;
double *euc;
double *coo;
float *feuc;
float angle;
float *v1;
float *v2;
float *v3;
int idx;
{
     int i,j,k;
     float v23[3],x,y,z,x2,y2,cosa,sina;
     double cc;

     cosa = cos(angle);
     sina = sin(angle);

     for (k=0; k < ndocka; k++) {

	 if (jact[idx][k] == 1 && k != ia1 && k != ia2) {

	   for (j=0; j < 3; j++) {
		v23[j] = (float) (coo[k*3+j] - coo[ia2*3+j]);
	   }

	   IMPRD(v1,v23,&z,0);
	   IMPRD(v2,v23,&y,0);
	   IMPRD(v3,v23,&x,0);

	   x2 = (cosa*x - sina*y);
	   y2 = (sina*x + cosa*y);

// new coordinates

	   for (j=0; j < 3; j++) {
		cc = (double) (v1[j]*z + v2[j]*y2 + v3[j]*x2);
		euc[k*3+j] = coo[ia2*3+j] + cc;
		feuc[k*3+j] = (float) euc[k*3+j];
	   }

	 } else {
	   for (j=0; j < 3; j++) {
		euc[k*3+j] = coo[k*3+j];
		feuc[k*3+j] = (float) euc[k*3+j];
	   }
	 }
     } // end for k

}

void cplig(euc,coo)
double *euc;
double *coo;
{
     int i,j;

     for (i=0; i < ndocka; i++) {
	for (j=0; j < 3; j++) {
	    euc[i*3+j] = coo[i*3+j];
	}
     }

}

void xyzROT3(double R[4][4],float vt[3]);
void xyzROT4(double R[4][4],float vt[3]);

int TransInter(
	double *c1old,double *c2old,double *c3old,double *outold,double *cntold,
	double *c1new,double *c2new,double *c3new,double *outnew,double *cntnew,
	double R1[4][4],double R2[4][4],double t[3]);

#define EMINCUT 100.0

void RotLig(int itri,float *V1,float *V2,float *OUTROT,float R[][3],
	    double *euc,double *finc,float *feuc,float *emin,int *frg,
	    float *F,int *iclos,
	    float *q,float *vdwr,float *vdwe,
	    float *ql,float *vdwrl,float *vdwel)
{
  int m,n,l;
  float COO[3];
  float vl1,vl2,vl3,cl;
  float p2,p2a;
  float dir[3];
  double Vout[3],euct[3],el;

  for (m=0; m<ndocka; m++) {
		
// translate ligand coordinates to NEW center

	for (n=0; n<3; n++) {
	   COO[n] = ((float)TriArr[itri]->coo[m*3+n] - 
			            TriArr[itri]->Cen[n]);
	}
	cl = veclen(COO);

		
// project ligand coordinates onto perpendicular vectors V1,V2,OUTROT

	inprod(V1,COO,&Vout[0]);
	inprod(V2,COO,&Vout[1]);
	inprod(OUTROT,COO,&Vout[2]);

	for (l=0; l<3; l++) {
	   euct[l] = 0.0;
	   for (n=0; n<3; n++) {
	      euct[l] = euct[l] + (double) (R[l][n]*Vout[n]*cl);
	   }
	}
	el = dveclen(euct);

	for (l=0; l<3; l++) {
	   euc[m*3+l] = euct[0]*V1[l] + euct[1]*V2[l] +
				euct[2]*OUTROT[l]; 
	}
	for (l=0; l<3; l++) {
	   euc[m*3+l] = euc[m*3+l] +
			(double) TriArr[itri]->Cen[l];
	   feuc[m*3+l] = (float) euc[m*3+l];
	}

// now evaluate energy of rotated structure

	CaljFE(feuc,xyzp->coo,iclos,
               q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	p2 = p2 + p2a;

	if (p2 < *emin) {
	   *emin = p2;
	   cplig(finc,euc);
	}

  }
}

float RotOut(int itri,COOSTRU *xyz,
	   double *euc,double *finc,float *feuc,int *frg,
	   float *F,int *iclos,
	   float *q,float *vdwr,float *vdwe,
	   float *ql,float *vdwrl,float *vdwel)
{
   int i,j,k,l,m,n,ang1,ang2,ang3;
   float v1[3],v2[3],v3[3];
   float V1[3],V2[3],V3[3];
   float p2,p2a,OUTROT[3],OUTROTbck[3],dir[3];
   float vl1,vl2,vl3,cl,emin;
   float sna,csa,SNA,CSA,snb,csb;
   float COO[3],R[3][3];
   double Vout[3],el,euct[3],rimp1,rimp2,rimp3;

// This routine takes the outvector of the matched protein/ligand triangle
//
// - rotates it in the plane of (the first atom, the center: vector v1) and the 
//   outvector of the triangle. (first angle of rotation).
// - secondly it rotates the product of the first rotation, in the plane of 
//   the v1 and v1Xout
//
// This was designed to rotate the ligand structure around the sightly
// rotated outvector, in order to establish the orientation with the lowest
// energy. This routine is very slow. We saw the solution of the docking was
// rotated, this however was down to TriArr[]->spec being set, which caused
// the rotline routine being activated. This was clearly wrong for the
// docking of 4zt.xyz into 5ccr.pdb

   emin = EMINCUT;

   Calc_Centroid(TriArr[itri]);

   for (i=0; i < 3; i++) {
	v1[i] = TriArr[itri]->p1[i] - TriArr[itri]->Cen[i];
	v2[i] = TriArr[itri]->p2[i] - TriArr[itri]->Cen[i];
   }

   cross(v1,v2,TriArr[itri]->Out);
   
   fnormalize(TriArr[itri]->Out);

   cross(v1,TriArr[itri]->Out,v2);

   fnormalize(v1);
   fnormalize(v2);

   for (j=1; j<3; j++) {

      ang1 = j*5;
      Get_FTsin(ang1,&sna,&csa);

      for (k=0; k<12; k++) {

// second rotation

	ang2 = k*30;
	Get_FTsin(ang2,&SNA,&CSA);

	for (i=0; i<3; i++) {
//	   OUTROT[i] = sna*(CSA*v1[i] + SNA*v2[i]) 
	   OUTROT[i] = sna*(SNA*v1[i] + CSA*v2[i]) 
			+ csa*TriArr[itri]->Out[i];
//	   OUTROT[i] =  TriArr[itri]->Out[i];
	}

//fprintf(stderr,"     %d  C   %.4f %.4f %.4f  C.ar   1 RES1 0.000\n",k+5,
//	OUTROT[0],OUTROT[1],OUTROT[2]);
	fnormalize(OUTROT);

// now do the rotation around OUTROT
// set up the three perpidicular vectors

	cross(v1,OUTROT,V2);
	cross(V2,OUTROT,V1);

	fnormalize(V1);
	fnormalize(V2);

        for (i=0; i<36; i++) {
	   ang3 = i*10;
	   Get_FTsin(ang3,&snb,&csb);

	   R[0][0] = csb; R[0][1] = -snb; R[0][2] = 0.0;
	   R[1][0] = snb; R[1][1] =  csb; R[1][2] = 0.0;
	   R[2][0] = 0.0; R[2][1] = 0.0;  R[2][2] = 1.0;
/*
	   R[0][0] = 1.0; R[0][1] = 0.0; R[0][2] = 0.0;
	   R[1][0] = 0.0; R[1][1] = 1.0; R[1][2] = 0.0;
	   R[2][0] = 0.0; R[2][1] = 0.0; R[2][2] = 1.0;
*/

	   RotLig(itri,V1,V2,OUTROT,R,
		euc,finc,feuc,&emin,frg,
		F,iclos,
		q,vdwr,vdwe,
		ql,vdwrl,vdwel);

	}
      }
   }

   if (emin != EMINCUT) {
	if (TriArr[itri]->coo != NULL) {
	   cplig(TriArr[itri]->coo,finc);
	}
   }
   return(emin);
}

float FindCooAngles(int ias[2][MXDIH], int sngs[MXDIH], 
			int ndih, int itri, int *iclos,int *frg,
			float *q,float *vdwr,float *vdwe,
			float *ql,float *vdwrl,float *vdwel,float *F,
			double *euc,double *coo,COOSTRU *xyz,
			int *nt,int it[MXTORS][4],
			float trs1[MXTORS][4],
			float trs2[MXTORS][4],
			float trs3[MXTORS][4],
			float trs4[MXTORS][4])
{
     int ang1,ang2,ang3,ang4,i,j,size,k,opt,iter;
     float angle1,angle2,angle3,angle4,todeg;
     float p1,p2,p2a,pf,dir[3],emin,emint,tmin;
     float v1[3],v2[3],v3[3];
     float *feuc,*feuc1,*feuc2,*feuc3;
     double *euc1,*euc2,*euc3,*eucn,*finc;
     double c1o[3],c2o[3],c3o[3],cnto[3],outo[3];
     double c1n[3],c2n[3],c3n[3],cntn[3],outn[3];
     double R1[4][4],R2[4][4],t[3];
     char cstr[19];
     char fname[1024];

     allFConf(&feuc,ndocka);
     allFConf(&feuc1,ndocka);
     allFConf(&feuc2,ndocka);
     allFConf(&feuc3,ndocka);
     allConf(&euc1,ndocka);
     allConf(&eucn,ndocka);
     allConf(&euc2,ndocka);
     allConf(&euc3,ndocka);
     allConf(&finc,ndocka);

// need buffer to store orig coordinates !! Can be feuc ???
// coo has the ligand pose

     todeg = 45.0 / atan(1.0);
     iter = -1;

     emin = EMINCUT;
     emint = EMINCUT;
     tmin = BIGD;
 
//     emin = RotOut(itri,xyz,euc,finc,feuc,frg,
//	            F,iclos,q,vdwr,vdwe,ql,vdwrl,vdwel);

     for (ang1=-2; ang1 < 3; ang1++) {

	iter++;
	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][0],ias[1][0],v1,v2,v3,itri,xyz);
	RotDih(ias[0][0],ias[1][0],euc,coo,feuc,angle1,v1,v2,v3,0);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,0) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[0]]) *nt = singleb.sngnt[sngs[0]];
	   p1 = CalTorS(sngs[0],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

// include self interaction ligand:

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		emint = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}

	if (ndih > 1) {

	 for (ang2=-2; ang2 < 3; ang2++) {

	   iter++;
	   angle2 = (((float) ang2)*30.0)/todeg;
	   Create_Vecs(ias[0][1],ias[1][1],v1,v2,v3,itri,xyz);
	   RotDih(ias[0][1],ias[1][1],euc1,euc,feuc1,angle2,v1,v2,v3,1);

	   if (CalClash(iclos,itri,vdwr,vdwrl,euc1,1) == BIGD) {
		continue;
	   } else {

		if (singleb.sngdone[sngs[1]]) *nt = singleb.sngnt[sngs[1]];
		p1 = CalTorS(sngs[1],xyz,euc1,nt,it,trs1,trs2,trs3,trs4);

		CaljFE(feuc1,xyzp->coo,iclos,
			q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

// include self interaction ligand:

		CalcFEL(&DCKxyz,feuc1,ql,vdwrl,vdwel,F,&p2a,dir);

		p2 = p2 + p2a;

	        if (p2 < emin) {
		   emin = p2;
		   emint = p2;
		   tmin = p1;
		   cplig(finc,euc1);
		}

	   }

	   if (ndih > 2) {

	      for (ang3=-2; ang3 < 3; ang3++) {

		angle3 = (((float) ang3)*30.0)/todeg;
		Create_Vecs(ias[0][2],ias[1][2],v1,v2,v3,itri,xyz);
	   	RotDih(ias[0][2],ias[1][2],euc2,euc1,feuc2,angle3,
			v1,v2,v3,2);

		if (CalClash(iclos,itri,vdwr,vdwrl,euc2,2) == BIGD) {
		   continue;
		} else {


		   if (singleb.sngdone[sngs[2]]) *nt = singleb.sngnt[sngs[2]];
		   p1 = CalTorS(sngs[2],xyz,euc2,nt,it,trs1,trs2,trs3,trs4);

		   CaljFE(feuc2,xyzp->coo,iclos,
			q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

// include self interaction ligand:

		   CalcFEL(&DCKxyz,feuc2,ql,vdwrl,vdwel,F,&p2a,dir);

		   p2 = p2 + p2a;

	           if (p2 < emin) {
			emin = p2;
			emint = p2;
			tmin = p1;
			cplig(finc,euc2);
		   }

		}

		if (ndih > 3) {

		  for (ang4=-2; ang4 < 3; ang4++) {

	   	   iter++;
		   angle4 = (((float) ang4)*30.0)/todeg;
		   Create_Vecs(ias[0][3],ias[1][3],v1,v2,v3,itri,xyz);
	   	   RotDih(ias[0][3],ias[1][3],euc3,euc2,feuc3,angle4,
				v1,v2,v3,3);
		   if (CalClash(iclos,itri,vdwr,vdwrl,euc3,3) == BIGD) {
			continue;
		   } else {
			if (singleb.sngdone[sngs[3]]) 
				*nt = singleb.sngnt[sngs[3]];
			p1 = CalTorS(sngs[3],xyz,euc3,
				nt,it,trs1,trs2,trs3,trs4);

			CaljFE(feuc3,xyzp->coo,iclos,
				q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

			p2 = p2 + p2a;

			if (p2+p2a < emint) {
			   emint = p2+p2a;
			}

	                if (p2 < emin) {
			   emin = p2;
			   tmin = p1;
			   cplig(finc,euc3);
			}
		   }
		  }
		}

	      }
	   }

	 }
	}
     }


     if (ndih > 4) {

      for (ang1=-2; ang1 < 3; ang1++) {

	iter++;
	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][4],ias[1][4],v1,v2,v3,itri,xyz);
	RotDih(ias[0][4],ias[1][4],euc,coo,feuc,angle1,v1,v2,v3,4);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,4) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[4]]) *nt = singleb.sngnt[sngs[4]];
	   p1 = CalTorS(sngs[4],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}

	if (ndih > 5) {

	 for (ang2=-2; ang2 < 3; ang2++) {

	   iter++;
	   angle2 = (((float) ang2)*30.0)/todeg;
	   Create_Vecs(ias[0][5],ias[1][5],v1,v2,v3,itri,xyz);
	   RotDih(ias[0][5],ias[1][5],euc1,euc,feuc1,angle2,v1,v2,v3,5);

	   if (CalClash(iclos,itri,vdwr,vdwrl,euc1,5) == BIGD) {
		continue;
	   } else {

	        if (singleb.sngdone[sngs[5]]) *nt = singleb.sngnt[sngs[5]];
		p1 = CalTorS(sngs[5],xyz,euc1,nt,it,trs1,trs2,trs3,trs4);

		CaljFE(feuc1,xyzp->coo,iclos,
			q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   	CalcFEL(&DCKxyz,feuc1,ql,vdwrl,vdwel,F,&p2a,dir);

	   	p2 = p2 + p2a;

	        if (p2 < emin) {
		   emin = p2;
		   tmin = p1;
		   cplig(finc,euc1);
		}

	   }

	   if (ndih > 6) {

      	      for (ang3=-2; ang3 < 3; ang3++) {

		angle3 = (((float) ang3)*30.0)/todeg;
		Create_Vecs(ias[0][6],ias[1][6],v1,v2,v3,itri,xyz);
		RotDih(ias[0][6],ias[1][6],euc2,euc,feuc2,angle3,v1,v2,v3,6);


		if (CalClash(iclos,itri,vdwr,vdwrl,euc2,6) == BIGD) {
		    continue;
		} else {

	           if (singleb.sngdone[sngs[6]]) *nt = singleb.sngnt[sngs[6]];
		   p1 = CalTorS(sngs[6],xyz,euc2,nt,it,trs1,trs2,trs3,trs4);

		   CaljFE(feuc2,xyzp->coo,iclos,
			q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   	   CalcFEL(&DCKxyz,feuc2,ql,vdwrl,vdwel,F,&p2a,dir);

	   	   p2 = p2 + p2a;

	           if (p2 < emin) {
		      emin = p2;
		      tmin = p1;
		      cplig(finc,euc2);
		   }

	       }
	 }
	 
	} 
	 }
	}
      }
     }

     if (ndih > 7) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][7],ias[1][7],v1,v2,v3,itri,xyz);
	RotDih(ias[0][7],ias[1][7],euc,coo,feuc,angle1,v1,v2,v3,7);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,7) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[7]]) *nt = singleb.sngnt[sngs[7]];
	   p1 = CalTorS(sngs[7],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (ndih > 8) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][8],ias[1][8],v1,v2,v3,itri,xyz);
	RotDih(ias[0][8],ias[1][8],euc,coo,feuc,angle1,v1,v2,v3,8);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,8) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[8]]) *nt = singleb.sngnt[sngs[8]];
	   p1 = CalTorS(sngs[8],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (ndih > 9) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][9],ias[1][9],v1,v2,v3,itri,xyz);
	RotDih(ias[0][9],ias[1][9],euc,coo,feuc,angle1,v1,v2,v3,9);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,9) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[9]]) *nt = singleb.sngnt[sngs[9]];
	   p1 = CalTorS(sngs[9],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (ndih > 10) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][10],ias[1][10],v1,v2,v3,itri,xyz);
	RotDih(ias[0][10],ias[1][10],euc,coo,feuc,angle1,v1,v2,v3,10);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,10) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[10]]) *nt = singleb.sngnt[sngs[10]];
	   p1 = CalTorS(sngs[10],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (ndih > 11) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][11],ias[1][11],v1,v2,v3,itri,xyz);
	RotDih(ias[0][11],ias[1][11],euc,coo,feuc,angle1,v1,v2,v3,11);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,11) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[11]]) *nt = singleb.sngnt[sngs[11]];
	   p1 = CalTorS(sngs[11],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (ndih > 12) {
      for (ang1=-2; ang1 < 3; ang1++) {

	angle1 = (((float) ang1)*30.0)/todeg;
	Create_Vecs(ias[0][12],ias[1][12],v1,v2,v3,itri,xyz);
	RotDih(ias[0][12],ias[1][12],euc,coo,feuc,angle1,v1,v2,v3,12);

	if (CalClash(iclos,itri,vdwr,vdwrl,euc,12) == BIGD) {

	   continue;

	} else {

	   if (singleb.sngdone[sngs[12]]) *nt = singleb.sngnt[sngs[12]];
	   p1 = CalTorS(sngs[12],xyz,euc,nt,it,trs1,trs2,trs3,trs4);

	   CaljFE(feuc,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel,F,&p2,dir,frg);

	   CalcFEL(&DCKxyz,feuc,ql,vdwrl,vdwel,F,&p2a,dir);

	   p2 = p2 + p2a;

	   if (p2 < emin) {
		emin = p2;
		tmin = p1;
		cplig(finc,euc);
	   }
	}
      }
     }

     if (emin == EMINCUT) {
	TriCooSafeFree(itri);
	TriSafeFreeTxt(itri,"FindCooAngles","Reason: eint > 0");
     } else {
	cplig(euc,finc);
     }

     vdwscal = 1.0;

     safefree((void **)&finc);
     safefree((void **)&euc1);
     safefree((void **)&euc2);
     safefree((void **)&euc3);
     safefree((void **)&feuc);
     safefree((void **)&feuc1);
     safefree((void **)&feuc2);
     safefree((void **)&feuc3);

if (debugdck) fprintf(stderr,"\nFindCooAngles: tmin %.3f Emin %.3f\n\n",tmin,emin);

     if (tmin == BIGD) tmin = 0.0;
     if (emin == BIGD) emin = 0.0;

     return(tmin+emin);
}


float FindOAngles(int ias[2][MXDIH], int sngs[MXDIH], 
		int ndih, int itri, int *iclos, int *frg,
		double *euc, COOSTRU *xyz, TRISTRU *tri,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel, float *F)
{
   int nt,k;
   int     it[MXTORS][4];
   float trs1[MXTORS][4];
   float trs2[MXTORS][4];
   float trs3[MXTORS][4];
   float trs4[MXTORS][4];
   float Emin;

   nt = 0;

// coo ligand pose in -> euc is adjusted optimised pose

   Emin = FindCooAngles(ias,sngs,ndih,itri,iclos,frg,
			q,vdwr,vdwe,
			ql,vdwrl,vdwel,F,
			euc,tri->coo,xyz,&nt,it,trs1,trs2,trs3,trs4);

   return(Emin);

}

float FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,co,coo,xyz,
			nt,it,trs1,trs2,trs3,trs4)
int isng;
int ic[4];
int ia2;
int itel;
float v1[3];
float v2[3];
float v3[3];
float angle;
double co[4][3];
double *coo;
COOSTRU *xyz;
int *nt;
int it[MXTORS][4];
float trs1[MXTORS][4];
float trs2[MXTORS][4];
float trs3[MXTORS][4];
float trs4[MXTORS][4];
{
     int i,j,in;
     float cosa,sina,v23[3],x,y,z,x2,y2,p1,p2;

       cosa = cos(angle);
       sina = sin(angle);

// restore original coordinates 

       for (i=0; i < itel; i++) {
	 if (ic[i] >= 0) {
	   for (j=0; j < 3; j++) {
		coo[ic[i]*3+j] = co[i][j];
	   }
	 }
       }

       for (i=0; i < itel; i++) {

	   in = ic[i];
	   if (in != -1) {

	      for (j=0; j < 3; j++) {
		v23[j] = (float) (coo[in*3+j] - coo[ia2*3+j]);
	      }

	      IMPRD(v1,v23,&z,0);
	      IMPRD(v2,v23,&y,0);
	      IMPRD(v3,v23,&x,0);

	      x2 = (cosa*x - sina*y);
	      y2 = (sina*x + cosa*y);

// new coordinates

	      for (j=0; j < 3; j++) {
		coo[in*3+j] = coo[ia2*3+j] +
				(v1[j]*z + v2[j]*y2 + v3[j]*x2);
	      }
	   }
        }
	if (singleb.sngdone[isng]) *nt = singleb.sngnt[isng];
	p1 = CalTorS(isng,xyz,coo,nt,it,trs1,trs2,trs3,trs4);
        p2 = vdwS(isng,xyz,coo);
	return(p1+p2);

}

void FindTorValues(isng,first,ic,ia2,itel,inum,v1,v2,v3,angle,toropt,
			co,coo,xyz,nt,it,trs1,trs2,trs3,trs4)
int isng;
int first;
int ic[4];
int ia2;
int itel;
int inum;
float v1[3];
float v2[3];
float v3[3];
float angle[4];
float toropt[4];
double co[4][3];
double *coo;
COOSTRU *xyz;
int *nt;
int it[MXTORS][4];
float trs1[MXTORS][4];
float trs2[MXTORS][4];
float trs3[MXTORS][4];
float trs4[MXTORS][4];
{
    int j;
    float torm,anga,todeg;

    todeg = 45.0 / atan(1.0);
    torm = BIGD;

    for (j=0; j < inum; j++) {
	   anga = angle[j]/todeg;

	   if (first) {
		toropt[j] = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,
				anga, co,xyz->coo,xyz,
				nt,it,trs1,trs2,trs3,trs4);
	   } else {
		toropt[j] = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,
				anga, co,coo,xyz,
				nt,it,trs1,trs2,trs3,trs4);
	   }
	   if (toropt[j] < torm) torm = toropt[j];
    }

    for (j=0; j < inum; j++) {
	   toropt[j] = toropt[j] - torm;
    }

}

int IsSp2Sp3(isng,xyz)
int isng;
COOSTRU *xyz;
{
      int i,ia1,ia2,ia3,ia4,na1,na2;
      int ianz[2],itel;

      ia1 = singleb.sng[isng][0];
      ia2 = singleb.sng[isng][1];

      na1 = xyz->iconn[ia1*(MXCON+1)];
      na2 = xyz->iconn[ia2*(MXCON+1)];

      itel = -1;
      if (na1 == 4 && na2 == 3) {
        for (i=0; i < xyz->iconn[ia2*(MXCON+1)]; i++) {
	   ia4 = xyz->iconn[ia2*(MXCON+1)+1+i] - 1;
	   if (ia4 != ia1) {
	  	if (itel == -1 || itel == 0) {
		    itel++;
		    ianz[itel] = xyz->ianz[ia4];
		}
	   }
	}
	if ((ianz[0] == 8 && ianz[1] == 6) ||
	    (ianz[0] == 6 && ianz[1] == 8)) return(1);


      }

      return(0);
}

void FindAngles(int first, int ia2, int isng, int itel, int dup, int *ic,
		COOSTRU *xyz, double co[4][3], double *coo,
		float *v1, float *v2, float *v3,
		float *angopt, float *toropt)
{
   int i,j,ang,angp1,angm1,ango[4],nt,nprof,err,ia1;
   float cosa,sina,angle,todeg,oute,prof[36],torm;
   float anglep5,anglem5,outep5,outem5,avang;
   int it[MXTORS][4];
   float trs1[MXTORS][4];
   float trs2[MXTORS][4];
   float trs3[MXTORS][4];
   float trs4[MXTORS][4];

   todeg = 45.0 / atan(1.0);

   nprof = 0;
   ia1 = singleb.sng[isng][0];

   if (!singleb.sngdone[isng]) {
	err = torset(ia1,ia2,&nt,it,trs1,trs2,trs3,trs4,
		xyz->iconn,singleb.ityp);
	singleb.sngnt[isng] = nt;
	singleb.sngdone[isng] = 1;
	for (i=0; i < nt; i++) {
	   for (j=0; j < 4; j++) {
		singleb.it[isng][i][j] = it[i][j];
		singleb.trs1[isng][i][j] = trs1[i][j];
		singleb.trs2[isng][i][j] = trs2[i][j];
		singleb.trs3[isng][i][j] = trs3[i][j];
		singleb.trs4[isng][i][j] = trs4[i][j];
	   }
	}
   } else {
	nt = singleb.sngnt[isng];
	for (i=0; i < nt; i++) {
	   for (j=0; j < 4; j++) {
		it[i][j]   = singleb.it[isng][i][j];
		trs1[i][j] = singleb.trs1[isng][i][j];
		trs2[i][j] = singleb.trs2[isng][i][j];
		trs3[i][j] = singleb.trs3[isng][i][j];
		trs4[i][j] = singleb.trs4[isng][i][j];
	   }
	}
   }


   for (ang=0; ang < 36; ang++) {
	angle = (((float) ang)*10.0)/todeg;
	if (first) {
	  prof[ang] = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,xyz->coo,xyz,&nt,it,trs1,trs2,trs3,trs4);
	} else {
	  prof[ang] = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);
	}
	if (prof[ang] == 0.0) nprof++;

   }

   if (nprof == 36 && singleb.dupsng[isng] == 1) {
	toropt[0] = 0.0;
	angopt[0] = 0.0;
	return;
   }

   angopt[0] = -BIGD;
   angopt[1] = -BIGD;
   angopt[2] = -BIGD;
   angopt[3] = -BIGD;

   toropt[0] =  BIGD;
   toropt[1] =  BIGD;
   toropt[2] =  BIGD;
   toropt[3] =  BIGD;

   itel = -1;

   for (ang=0; ang < 36; ang++) {

	if (ang == 0) {
	   angm1 = 35;
	   angp1 = ang + 1;

	} else if (ang == 35) {
	   angm1 = ang - 1;
	   angp1 = 0;
	} else {
	   angm1 = ang - 1;
	   angp1 = ang + 1;
	}

	if (prof[ang] < prof[angm1] && prof[ang] < prof[angp1]) {
	   if (itel <= 2) {
	      itel++;
	      toropt[itel] = prof[ang];
	      angopt[itel] = ((float) ang)*10.0;
	      ango[itel]   = ang;
	   }
	}
   }

   itel++;

   if (itel == 2) toropt[2] = 0.0;

   for (i=0; i < itel; i++) {

	angle   = ango[i]*10 + 5 ;
	anglep5 = ((int) angle) / todeg;

	if (first) {
	  outep5 = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,anglep5,
			co,xyz->coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	} else {
	  outep5 = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,anglep5,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);
	}

	angle   = ango[i]*10 - 5 ;
	anglem5 = ((int) angle) / todeg;

	if (first) {
	  outem5 = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,anglem5,
			co,xyz->coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	} else {
	  outem5 = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,anglem5,
			co,coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	}

	if (outep5 < toropt[i]) {

	  toropt[i] = outep5;
	  angopt[i] = anglep5;

	  for (j=0; j < 5; j++) {

	    angle = ango[i]*10 + j + 1;
	    angle = ((int) angle) / todeg;

	    if (first) {
		oute = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,xyz->coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	    } else {
		oute = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	    }

	    if (oute < toropt[i]) {
		toropt[i] = oute;
	  	angopt[i] = angle;
	    }
		
	  }
	}

	if (outem5 < toropt[i]) {

	  toropt[i] = outem5;
	  angopt[i] = anglem5;

	  for (j=0; j < 5; j++) {

	    angle = ango[i]*10 - 5 + j;
	    angle = ((int) angle) / todeg;

	    if (first) {
		oute = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,xyz->coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	    } else {
		oute = FindOptAngles(isng,ic,ia2,itel,v1,v2,v3,angle,
			co,coo,xyz,
			&nt,it,trs1,trs2,trs3,trs4);
	    }

	    if (oute < toropt[i]) {
		toropt[i] = oute;
	  	angopt[i] = angle;
	    }
		
	  }
	}
   }

   if (itel == 0 || itel == 1) {

        if (itel == 0) {
	   angopt[0] = 0.0;
	   angopt[1] = 120.0;
	   angopt[2] = 240.0;

           FindTorValues(isng,first,ic,ia2,itel,3,v1,v2,v3,angopt,toropt,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);

	   itel = 3;

	} else if (itel == 1) {

	   angopt[0] = 0.0;
	   angopt[1] = 120.0;

           FindTorValues(isng,first,ic,ia2,itel,3,v1,v2,v3,angopt,toropt,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);
	   itel = 2;
	}

   } else if (itel == 2 && dup == 4) {

	angopt[0] = 0.0;
	angopt[1] = 180.0;
	angopt[2] = 90.0;
	angopt[3] = 270.0;

        FindTorValues(isng,first,ic,ia2,itel,4,v1,v2,v3,angopt,toropt,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);

	itel = 4;

   } else if (itel == 2 && dup == 2) {

	if (ABS(angopt[0] - angopt[1]) < 5.0) {
	   avang = (angopt[0] + angopt[1]) / 2.0;
	   if (ABS(avang) < ABS(180.0 - avang)) {
		angopt[1] = 180.0;
	   } else {
		angopt[1] = 0.0;
	   }
	}

        FindTorValues(isng,first,ic,ia2,itel,2,v1,v2,v3,angopt,toropt,
			co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);

   } else {

	if ( itel != -1) {
		FindTorValues(isng,first,ic,ia2,itel,itel,v1,v2,v3,
			angopt,toropt,co,coo,xyz,&nt,it,trs1,trs2,trs3,trs4);
	}
   }

   for (i=0; i < itel; i++) {
	for (j=0; j < 3; j++) {
	   if (first) {
		if (ic[i] != -1) xyz->coo[ic[i]*3+j] = co[i][j];
	   } else {
		if (ic[i] != -1) coo[ic[i]*3+j] = co[i][j];
	   }
	}
   }

}

float CalcInter(double *cool,double *coo,int *iclos,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel)
{
   int i,j,l;
   float vr[3],rv,rv2,rs2,rs3,rsum,rinv,epsm,p6,p12;
   float e,ev,eq,econv;

   ev = 0.0; eq = 0.0;
   econv = 332.05382;

   for (i=0; i < *xyzp->iatoms; i++) {
     if (iclos[i]) {
	for (j=0; j < ndocka; j++) {

	   for (l=0; l < 3; l++) {
		vr[l] =  (float) (cool[j*3+l] - coo[i*3+l]);
		vr[l] =  vr[l]*toangs;
	   }

	   rv2 = vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2];
	   rv = sqrt(rv2);
	   rinv = 1.0/rv;
	   rsum = vdwr[i] + vdwrl[j];
	   epsm = sqrt(vdwe[i]*vdwel[j]);
	   rs2 = rsum*rsum;
	   rs3 = rs2*rsum;
	   p6   = (rs3*rs3) / (rv2*rv2*rv2);
	   p12  = p6 * p6;

	   e    = epsm * (p12 - 2.0*p6);

	   ev   = ev + vdwscal*e;
   
	   e = q[i]*ql[j]*econv*rinv;

	   eq = eq + e;	
	}
     }
   }

   return(eq+ev);

}

void Conformers_Energies(xyz)
COOSTRU *xyz;
{
   int i,k,l,*iclos;
   float *q,*vdwr,*vdwe,*F;
   float Eintra,Einter;
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int nt;
   int     it[MXTORS][4];
   float trs1[MXTORS][4];
   float trs2[MXTORS][4];
   float trs3[MXTORS][4];
   float trs4[MXTORS][4];

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   if (ntris > 0) {
	vdwscal = VDWSCAL;
	vdwscal = vdwscal_memory;
   }

   nt = 0;

   if (debugdck) fprintf(stderr,"Conformers_Energies: ntris %d\n",ntris);

   for (k=0; k < ntris; k++) {

    if (TriArr[k] != NULL) {
      if (TriArr[k]->coo != NULL) {

	FillClos(iclos,k); 

	Eintra = 0.0;

	for (l=0; l < singleb.N; l++) {
	   if (singleb.sngdone[l]) nt = singleb.sngnt[l];
	   Eintra = Eintra +
		CalTorS(l,xyz,TriArr[k]->coo,&nt,it,trs1,trs2,trs3,trs4);
	}

	TriArr[k]->e12 = Eintra;

	Einter = CalcInter(TriArr[k]->coo,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel);

	TriArr[k]->eint = Einter;
	TriArr[k]->etot = Einter + Eintra;

      }
    }
   }

   Compress_Tri_L();

   vdwscal = 1.0;

   safefree((void **)&q);
   safefree((void **)&vdwr);
   safefree((void **)&vdwe);
   safefree((void **)&F);

   eint_calculated = 1;
}

int TransInter(
	double *c1old,double *c2old,double *c3old,double *outold,double *cntold,
	double *c1new,double *c2new,double *c3new,double *outnew,double *cntnew,
	double R1[4][4],double R2[4][4],double t[3])
{
   int i,j;
   float c1o[3],c2o[3],c3o[3],c1n[4],c2n[3],c3n[3],cnto[3],cntn[3];
   float c1c[3],c2c[3],c3c[3];
   float outo[3],outn[3];
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float COSA,SINA,cosa,sina,vl1,VL2;

   for (j = 0; j<3; j++ ) {
	t[j]  = (cntold[j] - cntnew[j]);
	v3[j] = (float) (c1old[j] - cntold[j]);
	V1[j] = (float) (c1new[j] - cntnew[j]);
	V2[j] = (float) outnew[j];

	cntnew[j] = cntnew[j] + t[j];
	cnto[j] = (float) cntold[j];
	cntn[j] = (float) cntnew[j];
	outo[j] = (float) outold[j];
	outn[j] = (float) outnew[j];
   }

   vecnrm(outn);
   vecnrm(outo);

   cross(outn,outo,v1);
   cross(outo,outn,v1);
   cross(outo,v1,v2);
   
   vecnrm(v1);
   vecnrm(v2);
   
   vl1 = veclen(v1);

   if (vl1 == 0.0) {
	for (i = 0; i<3; i++ ) {
	   for (j = 0; j<3; j++ ) {
		R1[i][j] = 0.0;
	   }
	}
	R1[0][0] = R1[1][1] = R1[2][2] = 1.0;
   } else {
	IMPRD(outn,outo,&cosa,1);
	IMPRD(outn,v2,&sina,1);

	Frst_Rot(cnto,v1,sina,cosa,R1);
   }

   vecnrm(V1);
   vecnrm(V2);
   
   xyzROT3(R1,V1);
   xyzROT3(R1,V2);
   xyzROT4(R1,cntn);

   cross(outo,v3,v2);

   vecnrm(v2);
   vecnrm(v3);
   vecnrm(outo);
   vecnrm(V1);
   cross(V2,V1,V3);

   VL2 = veclen(V2);

   if (VL2 == 0.0) {
	for (i = 0; i<3; i++ ) {
	   for (j = 0; j<3; j++ ) {
		R2[i][j] = 0.0;
	   }
	}
	R2[0][0] = R2[1][1] = R2[2][2] = 1.0;
   } else {
	IMPRD(v3,V1,&COSA,1);
	IMPRD(v3,V3,&SINA,1);

	Frst_Rot(cntn,V2,SINA,COSA,R2);
   }

   if (vl1 == 0.0 || VL2 == 0.0) return(1);
   return(0);
}

void Optimise_Conformers(ias,sngs,ndih,xyz)
int ias[2][MXDIH];
int sngs[MXDIH];
int ndih;
COOSTRU *xyz;
{
   int i,ii,j,k,*iclos;
   int ia1,ia2,ia3,ic[3],itel,isng;
   double *euc;
   float *q,*vdwr,*vdwe,*F,Etor;
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int frg[MXLIGA];
   time_t curtime;

   if (ndih == 0) return;

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;
   allConf(&euc,ndocka);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   for (k=0; k < MXLIGA; k++) frg[k] = 1;

   for (k=0; k < singleb.N; k++) singleb.sngdone[k] = 0;


// create orthogonal set of axes, v1,v2,v3: v1 is the rotation axis (z)

   vdwscal = vdwscal_memory;

   for (k=0; k < ntris; k++) {

      if (TriArr[k] == NULL) continue;

      if ((TriArr[k]->eint < 0.0 || !MapConformers) 
		&& TriArr[k]->coo != NULL) {


	if (DCKMETH == 0) {
	   FillOptD(iclos);
	} else {
	   FillOpt(iclos,k);
	}

	if (MapConformers) {

	   if (TriArr[k]->small) {
		PickFull(frg,ndocka);
	   } else {
		PickFrag(frg,k,ndocka);
	   }
	} else {
	   PickFull(frg,ndocka);
	}


	Etor = FindOAngles(ias,sngs,ndih,k,iclos,frg,
		euc,xyz,TriArr[k],
		q,vdwr,vdwe,
		ql,vdwrl,vdwe,F);

// toropt is not declared. But it also not correct the proove of the
// answer consists of two components: the torsion part is
// the real eint(ernal) part. The second has to do with
// ligand - protein interactions



	if (TriArr[k] != NULL && TriArr[k]->coo != NULL) {

	   if (Etor < 0.0 ) {

if (debugdck) fprintf(stderr,"Optimise_Conformers: Etor %.3f\n",Etor);

		TriArr[k]->eint = Etor;

		for (i=0; i < ndocka; i++) {
		   for (j=0; j < 3; j++) {
			TriArr[k]->coo[i*3+j] = euc[i*3+j];
		   }
		}
	   }
	}

     }
   }

   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);

   vdwscal = 1.0;
   eint_calculated = 1;
}

void Loop_Opt_Dih(Ifrag,xyz,ivis)
int Ifrag;
COOSTRU *xyz;
int ivis;
{
  int i,j,k,l,m,ia1,ia2,iact[MXLIGA],ifrag,jfrag,IFRG[9],NFRG,frg;
  int jfrg[9],nfrag,DFRG[MXLIGA];
  int ias[2][MXDIH],sngs[MXDIH],ndih;

  ndih = 0;
  IFRG[0] = Ifrag;
  NFRG = 1;

  for (i=0; i < MXDIH; i++) {
     for (k=0; k < MXLIGA; k++) {
	jact[i][k] = 0;
	jopt[i][k] = 0;
     }
  }

  for (k=0; k < singleb.NFRAG; k++) DFRG[k] = 0;

  while (1) {

   nfrag = 0;

   for (k=0; k < NFRG; k++) {

      ifrag = IFRG[k];
      if (ifrag > MXLIGA-1 || ifrag < 0) goto loop;
      DFRG[ifrag] = 1;

      for (j=0; j < singleb.FrgSngN[ifrag]; j++) {
	frg = 0;
	l = singleb.FrgSng[ifrag][j];

	if (!DFRG[singleb.SngFrg[l][0]] && DFRG[singleb.SngFrg[l][1]]) frg = 1;
	if (DFRG[singleb.SngFrg[l][0]] && !DFRG[singleb.SngFrg[l][1]]) frg = 1;

	if (frg) {
           for (i=0; i < ndocka; i++) iact[i] = 0;

	   jfrag = singleb.SngFrg[l][0];
	   if (!DFRG[jfrag]) jfrg[nfrag] = jfrag;

	   jfrag = singleb.SngFrg[l][1];
	   if (!DFRG[jfrag]) jfrg[nfrag] = jfrag;

	   if (singleb.ifrg[singleb.sng[l][0]] == ifrag) {
		ia1 = singleb.sng[l][0];
		ia2 = singleb.sng[l][1];
	   } else {
		ia2 = singleb.sng[l][0];
		ia1 = singleb.sng[l][1];
	   }

	   DFRG[jfrg[nfrag]] = 1;

	   if (singleb.dupsng[l] >= 2) {
	      if (ndih < MXDIH) {
		ias[0][ndih] = ia1;
		ias[1][ndih] = ia2;
		xyz->iatclr[ia1] = 15;
		xyz->iatclr[ia2] = 15;
		sngs[ndih] = l;
	   	if (Create_Act(ia1,ia2,iact,xyz)) {
		   for (m=0; m < ndocka; m++) {
			jact[ndih][m] = iact[m];
		   }
		   
	   	}
		ndih++;
	      }
	   }
	   if (singleb.FrgSngN[ifrag] >= 1) nfrag++;
	}
      }
   }
loop:
   if (nfrag == 0) goto OPT;

   NFRG = nfrag;
   for (k=0; k < NFRG; k++) IFRG[k] = jfrg[k];
  }

OPT:

  if (debugdck) fprintf(stderr,"Loop_Opt_Dih: ndih %d\n",ndih);

  for (k=0; k < ndih; k++) {
     for (i=0; i < ndocka; i++) {
	if (k == ndih-1) {
	   jopt[k][i] = jact[k][i];
	} else {
	   if (jact[k][i] == 1 && jact[k+1][i] == 0) {
		jopt[k][i] = 1;
	   } else {
		jopt[k][i] = 0;
	   }
	}
     }
  }

  if (!ivis) Optimise_Conformers(ias,sngs,ndih,xyz);

  return;

}

void Create_Conformers_Single(ia1,ia2,isng,iact,xyz)
int ia1;
int ia2;
int isng;
int *iact;
COOSTRU *xyz;
{
   int i,j,k,l;
   int ia3,ic[4],itel,ntrift,first;
   float v1[3],v2[3],v3[3],v23[3],vl,x,y,z,x2,y2;
   float cosa,sina,angle,todeg,angopt[4],toropt[4];
   double co[4][3];
   static TRISTRU *FinTmp[MAXSTRI];
   char tmps[13];

   todeg = 45.0 / atan(1.0);

   singleb.dupsng[isng] = IsSymFrg(isng,xyz);

// create orthogonal set of axes, v1,v2,v3: v1 is the rotation axis (z)

   if (ntrif == -1) {
	ntrift = 1;
	first = 1;
   } else {
	ntrift = ntrif;
	for (k=0; k < ntrift; k++) {
	   FinTmp[k] = TriFin[k];
	   TriFin[k] = NULL;
	}
	ntrif = -1;
	first = 0;
   }

   for (k=0; k < ntrift; k++) {

     for (j=0; j < 3; j++) {
	if (first) {
	   v1[j] = ((float) (xyz->coo[ia1*3+j] - xyz->coo[ia2*3+j]));
	} else {
	   v1[j] = ((float) (FinTmp[k]->coo[ia1*3+j] - FinTmp[k]->coo[ia2*3+j]));
	}
     }

     vl = veclen(v1);

     for (j=0; j < 3; j++) {
	v1[j] = v1[j] / vl;
     }

     for (i=0; i < xyz->iconn[ia2*(MXCON+1)]; i++) {

	ia3 = xyz->iconn[ia2*(MXCON+1)+1+i] - 1;

	if (ia3 != ia1) {
	   for (j=0; j < 3; j++) {
		if (first) {
		   v23[j] = ((float) (xyz->coo[ia3*3+j] - 
				xyz->coo[ia2*3+j]));
		} else {
		   v23[j] = ((float) (FinTmp[k]->coo[ia3*3+j] - 
				FinTmp[k]->coo[ia2*3+j]));
		}
	   }
	   break;
	}

     }

     cross(v1,v23,v2);

     vl = veclen(v2);

     for (j=0; j < 3; j++) {
	v2[j] = v2[j] / vl;
     }

     cross(v1,v2,v3);
 
// retrieve the three atoms connected to ia2, that need to be rotated

     itel = -1;

     ic[0] = -1; ic[1] = -1; ic[2] = -1; ic[3] = -1;

     for (i=0; i < xyz->iconn[ia2*(MXCON+1)]; i++) {

       ia3 = xyz->iconn[ia2*(MXCON+1)+1+i] - 1;

       if (ia3 != ia1) {
	  itel++;
	  ic[itel] = ia3;

	  for (j=0; j < 3; j++) {
	     if (first) {
		co[itel][j] = xyz->coo[ic[itel]*3+j];
	     } else {
		co[itel][j] = FinTmp[k]->coo[ic[itel]*3+j];
	     }
	  }
       }
     }

     itel++;

// find three optimal angles for rotation
// allocate play temporary structure,such that etors can be calculated

     if (first) {
	FindAngles(first,ia2,isng,itel,singleb.dupsng[isng],ic,
		xyz,co,NULL,
		v1,v2,v3,angopt,toropt);
     } else {
	FindAngles(first,ia2,isng,itel,singleb.dupsng[isng],ic,
		xyz,co,FinTmp[k]->coo,
		v1,v2,v3,angopt,toropt);
     }


// now create max three new conformations
   
     if (IsSp2Sp3(isng,xyz)) {
	angopt[0] = 0.0;
	angopt[1] = 120.0;
	angopt[2] = 240.0;
     }

     for (l=0; l < singleb.dupsng[isng]; l++) {

	angle = angopt[l]/todeg;
	cosa  = cos(angle);
	sina  = sin(angle);

	if (ntrif >= MAXSTRI-1) return;

	ntrif++;
	if (TriFin[ntrif] == NULL) {
	   TriAll(&TriFin[ntrif]);
	}

	allConf(&TriFin[ntrif]->coo,ndocka);

 	TriFin[ntrif]->conf = ntrif;

// allocated space for new conformer,but what to copy into it ?
// docked base fragment ?? Or loop over placements of base fragments ??

	if (first) {
	   TriFin[ntrif]->eint = 0.0;
	} else {
	   TriFin[ntrif]->eint = FinTmp[k]->eint + toropt[l];
	}

	for (i=0; i < ndocka; i++) {
         for (j=0; j<3; j++) {
	   if (first) {
		TriFin[ntrif]->coo[i*3+j] = xyz->coo[i*3+j];
	   } else {
		TriFin[ntrif]->coo[i*3+j] = FinTmp[k]->coo[i*3+j];
	   }
         }
	}

	for (i=0; i < ndocka; i++) {

	   if (iact[i] == 1 && i != ia1 && i != ia2) {
	      for (j=0; j < 3; j++) {
		v23[j] = ((float) (TriFin[ntrif]->coo[i*3+j] - 
				TriFin[ntrif]->coo[ia2*3+j]));
	      }
	      IMPRD(v1,v23,&z,0);
	      IMPRD(v2,v23,&y,0);
	      IMPRD(v3,v23,&x,0);

// x2 and y2 could be reversed

	      x2 = (cosa*x - sina*y);
	      y2 = (sina*x + cosa*y);

	      for (j=0; j < 3; j++) {
		TriFin[ntrif]->coo[i*3+j] =  TriFin[ntrif]->coo[ia2*3+j] +
				v1[j]*z + v2[j]*y2 + v3[j]*x2;
	      }
	   }
	}
     }

     if (ntrift != 1 && first) {
	if (FinTmp[k]->coo != NULL) safefree((void **)&FinTmp[k]->coo);
	safefree((void **)&FinTmp[k]);
     }
   }

   ntrif++;

}

int Create_Act(IA1,IA2,iact,xyz)
int IA1;
int IA2;
int iact[MXLIGA];
COOSTRU *xyz;
{
   int i,j,k,ia1,ia2,ia3,iflg;
   int icn[MXLIGA],icno[MXLIGA],ICN[MXLIGA],ICNO[MXLIGA],ncn,NCN,ndck;


   for (j=0; j < MXLIGA; j++) {
	icn[j] = 0;
	icno[j] = 0;
	ICN[j] = -1;
	ICNO[j] = -1;
   }

   ICN[0]  = IA2;
   ICNO[0] = IA1;
   NCN = 1;

NEXTR:
   ncn = -1;

   for (j=0; j < NCN; j++) {
      ia2 = ICN[j];
      ia1 = ICNO[j];
      for (i=0; i < xyz->iconn[ia2*(MXCON+1)]; i++) {
	ia3 = xyz->iconn[ia2*(MXCON+1)+1+i] - 1;
	if (ia3 != ia1 && iact[ia3] == 0) {
	   iflg = 0;
	   for (k=0; k < ncn; k++) {
		if (icn[k] == ia3) iflg = 1;
	   }
	   if (!iflg) {
		iact[ia3] = 1;
		if (ncn < MXLIGA-1) {
		   ncn++;
		   icn[ncn]  = ia3;
		   icno[ncn] = ia2;
		} else {
		   ncn = -1;
		}
	   }
	}
      }
   }
   ncn++;

   ndck = 0;
   for (j=0; j < ndocka; j++) {
	if (iact[j] == 1) ndck++;
   }

   if (ncn == 0) {
	if (ndck == ndocka) return(0);
	return(1);
   }

   NCN = ncn;
   for (i=0; i < NCN; i++) {
	ICN[i]  = icn[i];
	ICNO[i] = icno[i];
   }
   goto NEXTR;
   return(0);
}

// what about xyz, have to pass on to Create_Conformers_Single ?

void CopyLig(xyz)
COOSTRU *xyz;
{
   int i,j;

   if (TriFin[0] == NULL) 
	   TriAll(&TriFin[0]);
   allConf(&TriFin[0]->coo,ndocka);

   for (i=0; i < ndocka; i++) {
      for (j = 0; j < 3; j++ ) {
	TriFin[0]->coo[i*3+j] = xyz->coo[i*3+j];
      }
   }

   ntrif = 1;
}

void Sanitise_Conformers()
{
   int i;

   for (i=0; i < ntrif; i++) {
	if (TriFin[i]->eint >= BIGD) 
		TriFin[i]->eint = TriFin[i]->eint - BIGD;
	if (TriFin[i]->eint >= BIGD) 
		TriFin[i]->eint = TriFin[i]->eint - BIGD;
   }
}

void Create_Conformers(Ifrag,xyz)
int Ifrag;
COOSTRU *xyz;
{
   int i,j,k,l,ia1,ia2,iact[MXLIGA],ifrag,jfrag,IFRG[9],NFRG,frg;
   int jfrg[9],nfrag,DFRG[MXLIGA];

   IFRG[0] = Ifrag;
   NFRG = 1;

   for (k=0; k < singleb.NFRAG; k++) DFRG[k] = 0;

while (1) {

   nfrag = 0;
   for (k=0; k < NFRG; k++) {

      if (k > 8) return;
      ifrag = IFRG[k];
      if (ifrag == -1) return;
      if (ifrag > MXLIGA-1 || ifrag < 0) goto loop;

      DFRG[ifrag] = 1;

      for (j=0; j < singleb.FrgSngN[ifrag]; j++) {
	frg = 0;
	l = singleb.FrgSng[ifrag][j];

	if (!DFRG[singleb.SngFrg[l][0]] && DFRG[singleb.SngFrg[l][1]]) frg = 1;
	if (DFRG[singleb.SngFrg[l][0]] && !DFRG[singleb.SngFrg[l][1]]) frg = 1;

	if (frg) {
           for (i=0; i < ndocka; i++) iact[i] = 0;

	   jfrag = singleb.SngFrg[l][0];
	   if (!DFRG[jfrag]) jfrg[nfrag] = jfrag;

	   jfrag = singleb.SngFrg[l][1];
	   if (!DFRG[jfrag]) jfrg[nfrag] = jfrag;

	   if (singleb.ifrg[singleb.sng[l][0]] == ifrag) {
		ia1 = singleb.sng[l][0];
		ia2 = singleb.sng[l][1];
	   } else {
		ia2 = singleb.sng[l][0];
		ia1 = singleb.sng[l][1];
	   }

	   DFRG[jfrg[nfrag]] = 1;

	   if (Create_Act(ia1,ia2,iact,xyz)) {
	   }
	   Create_Conformers_Single(ia1,ia2,l,iact,xyz);
	   if (singleb.FrgSngN[ifrag] >= 1) nfrag++;
	}
      }
   }

loop:
   if (nfrag == 0) return;

   NFRG = nfrag;
   for (k=0; k < NFRG; k++) IFRG[k] = jfrg[k];
}

// This only takes care of the first series of connected. NOT
// the ones connected to those !!
}

 
double dst(Tri1,Tri2)
TRISTRU *Tri1;
TRISTRU *Tri2;
{
   int i,j;
   double dd,tt;

   dd = 0.0;

   for (i = 0; i < ndocka; i++ ) {
      for (j = 0; j < 3; j++ ) {
	tt = (Tri1->coo[i*3+j] - Tri2->coo[i*3+j]);
	dd = dd + tt*tt;
      }
   }
   dd = dd / ndocka;
   dd = sqrt(dd);
   return(dd);
}

double dst_coo(xyzp1,xyzp2,nato1,nato2)
COOSTRU *xyzp1;
COOSTRU *xyzp2;
int nato1;
int nato2;
{
   int i,j;
   double dd,tt;

   dd = 0.0;

   if (nato2 < nato1) return(-1.0);

   for (i = 0; i < nato1; i++ ) {
      for (j = 0; j < 3; j++ ) {
	tt = (xyzp1->coo[i*3+j] - xyzp2->coo[i*3+j])*toangs;
	dd = dd + tt*tt;
      }
   }
   dd = dd / (nato1);
   dd = sqrt(dd);
   return(dd);
}

static int cmpldat(a,b)
LDAT *a, *b;
{
    if (a->dd > b->dd) return 1;
    else
       if (a->dd == b->dd) return  0;
       else          return -1;
}

static int cmptri(const void * a,const void * b)
{
    TRISTRU **Tria = (TRISTRU **) a;
    TRISTRU **Trib = (TRISTRU **) b;
    if ((*Tria) == NULL || (*Trib) == NULL) return 0;
    if ((*Tria)->e12 > (*Trib)->e12) return  1;
    if ((*Tria)->e12 < (*Trib)->e12) return -1;
    return 0;
    
}

static int ldateq(a,b)
LDAT *a, *b;
{
    if (a->dd == b->dd && a->i == b->i && a->j == b->j) return 1;
    return 0;
}

void dsply_List(node *begin)
{
    int n,i;
    node *p;
    
    n = 0;
    if (begin == NULL) {
        fprintf(stderr,"List is empty\n");
        return;
    }

    p = begin;

    fprintf(stderr,"List is :\n");

    while (p != NULL) {
        fprintf(stderr,"(i=%d,j=%d,dd=%f,stat=%d)",
		p->info.i,p->info.j,p->info.dd,p->info.stat);

	if (p->info.N > 0) {
           fprintf(stderr,"(Arr=");
	   for (i=0; i<p->info.N; i++) {
		fprintf(stderr,"%3d,",p->info.Arr[i]);
	   }
	}
        fprintf(stderr,")\n");


        p = p->next_node;
	n++;
    }

    fprintf(stderr,"\n");
    fprintf(stderr,"# %d Elemnts\n",n);
}
 
void set_List(node *begin,node **barr,int *N,int MXARR)
{
    node *p;
    
    *N = 0;
    if (begin == NULL) return;

    p = begin;

    while(p != NULL) {
	barr[*N] = p;
        p = p->next_node;
	(*N)++;
	if (*N == MXARR) return;
    }
}

int max_List(node *begin)
{
    node *p;
    LDAT info;
    int mx;
    
    mx = 0;
    if (begin == NULL) return(mx);

    p = begin;
    info = p->info;
    mx = info.i;
    if (info.j > mx) mx = info.j;

    while(p != NULL) {
	info = p->info;
	if (info.i > mx) mx = info.i;
	if (info.j > mx) mx = info.j;
        p = p->next_node;
    }

    return(mx);
}

void upd_List(node **barr,int *N,node *delnode)
{
    int i,j;

    for (i=0; i < *N; i++) {
	if (barr[i] == delnode) {
	   (*N)--;
	   for (j=i; j < *N; j++) {
		barr[j] = barr[j+1];
	   }
	}
    }
}

void replc_List(node *begin,int val,int nval)
{
    int n,i,j;
    node *p;
    
    n = 0;

    if (begin==NULL) {
        return;
    }

    p = begin;
    while (p != NULL) {
	i = p->info.i; j = p->info.j;
	if (i == val || j == val) {
	   if (i == val) i = nval;
	   if (j == val) j = nval;
	   if (i < j) {
		   p->info.i = i;
		   p->info.j = j;
	   } else {
		   p->info.i = j;
		   p->info.j = i;
	   }
	}
        p=p->next_node;
	n++;
    }
}
 
node *addtoemptylist(node *begin,LDAT data_element)
{
    node *temp;
    temp=(node *)malloc(sizeof(node));
    temp->info=data_element;
    temp->prev_node=NULL;
    temp->next_node=NULL;
    begin=temp;
    return begin;
}
 
node *addatendlist(node *begin,LDAT data_element)
{
    node *temp,*p;

    if (begin == NULL) {
        printf("List is empty\n");
        return NULL;
    }
 
    temp = (node *) malloc(sizeof(node));
    temp->info = data_element;

    p=begin;
    while (p->next_node != NULL)
        p=p->next_node;

    p->next_node=temp;
    temp->next_node=NULL;
    temp->prev_node=p;
    return begin;
}
 
node *insertdd(node *begin,node **barr,int *N,LDAT data_element)
{
    node *temp,*p,*tp,*tn;
    int n;

    temp = (node *) malloc(sizeof(node));
    temp->info = data_element;
    temp->next_node = NULL;
    temp->prev_node = NULL;

    p = begin;
    tp = NULL;

    n = 0;
    while (p != NULL) {
        if (p->next_node == NULL)  {

            temp->prev_node=p;
            temp->next_node=p->next_node;
            p->next_node = temp;
	    goto NEXT;

	} else if (p->prev_node == NULL) {
	   if (p->info.dd < data_element.dd) {
              temp->prev_node = NULL;
              temp->next_node= p;
              p->prev_node = temp;
	      begin = temp;
	      goto NEXT;
	   }

	} else {

	   if (p->info.dd < data_element.dd && 
	    p->next_node->info.dd >= data_element.dd) {

            temp->prev_node=p;
            temp->next_node=p->next_node;

            p->next_node->prev_node = temp;

            p->next_node = temp;
	    goto NEXT;
           }

        }
	tp = p;
        p = p->next_node;
	n++;
    }
NEXT:
    return begin;
}
 
node *deletenode(node *begin,node *delnode,LDAT *data_element,node **barr,int *N)
{
    node *temp,*tp,*tn;

    if (begin == NULL) {
	goto NEXT;
    }

    if (begin->next_node == NULL) {  
        if (begin->info.i == data_element->i && 
		begin->info.j == data_element->j) {
            temp  = begin;
            begin = NULL;
	    data_element->dd = temp->info.dd;
	    delnode = begin;

        } else {
	    delnode = NULL;

        }
	goto NEXT;
    }
    

    if (begin->info.i == data_element->i && 
	begin->info.j == data_element->j) {

        temp=begin;
	data_element->dd = temp->info.dd;
        begin=begin->next_node;  
        begin->prev_node=NULL;
	delnode = begin;
	goto NEXT;
    }
 
    temp=begin->next_node;
    tp = begin;
    tn = temp->next_node;

    while (temp->next_node != NULL) {

        if (temp->info.i == data_element->i && 
		temp->info.j == data_element->j) {

            if (tp != NULL) {
		if (tp->next_node != NULL) {
		   tp->next_node = temp->next_node;
		}
	    }
            if (tn != NULL) {
		tn->prev_node = temp->prev_node;
	    }
	    delnode = temp;
	    goto NEXT;
        }
	tp = temp;
        temp=temp->next_node;
	tn = temp->next_node;
    }
 
    if (temp->info.i == data_element->i && 
	temp->info.j == data_element->j) {
	data_element->dd = temp->info.dd;

        temp->prev_node->next_node=NULL;
	delnode = temp;
	goto NEXT;
    }

    delnode = NULL;
NEXT:
    upd_List(barr,N,delnode);
    return begin;
}
 
node *dlnode(node *p,LDAT *data_element)
{
    node *temp,*tp,*tn,*ipp;
    int ip = 0;

    if (p == NULL) {
	goto NEXT;
    }

    if (p->next_node == NULL) {  
        if (p->info.i == data_element->i && 
		p->info.j == data_element->j) {
            temp  = p;
            p = NULL;
	    data_element->dd = temp->info.dd;
        }
	goto NEXT;
    }
    

    if (p->info.i == data_element->i && 
	p->info.j == data_element->j) {

        temp=p;
	data_element->dd = temp->info.dd;
	ipp = p->prev_node;
        p=p->next_node;  
	p->prev_node=ipp;
	goto NEXT;
    }
 
    temp=p->next_node;
    tp = p;
    tn = temp->next_node;

    while (temp->next_node != NULL) {

        if (temp->info.i == data_element->i && 
		temp->info.j == data_element->j) {

            if (tp != NULL) {
		if (tp->next_node != NULL) {
		   tp->next_node = temp->next_node;
		}
	    }
            if (tn != NULL) {
		tn->prev_node = temp->prev_node;
	    }
	    goto NEXT;
        }
	tp = temp;
        temp=temp->next_node;
	tn = temp->next_node;
    }
 
    if (temp->info.i == data_element->i && 
	temp->info.j == data_element->j) {
	data_element->dd = temp->info.dd;

        temp->prev_node->next_node=NULL;
	goto NEXT;
    }

NEXT:
    return p;
}
 
void Add2Delarr(node *delnode,node **delarr,int *N,int MXARR)
{
    if (delnode == NULL) return;

    if (*N < MXARR) {
	delarr[(*N)] =  delnode;
	(*N)++;
    }
}

void FreeDelarr(node **delarr,int *N)
{
    int i;

    for (i=0; i < *N; i++) {
	if (delarr[i] != NULL) safefree((void **)&delarr[i]);
    }
}

LDAT get_info(node *begin,LDAT data_element)
{
    node *temp;
    LDAT nulinfo;

    nulinfo.i = -1; nulinfo.j = -1;
    if (begin == NULL) {
        return nulinfo;
    }

    if (begin->next_node == NULL) {  

        if (begin->info.i == data_element.i && 
		begin->info.j == data_element.j) {
            return begin->info;
        } else {
            return nulinfo;
        }
    }
    

    if (begin->info.i == data_element.i && 
		begin->info.j == data_element.j) {
        return begin->info;
    }
 
    temp = begin->next_node;

    while (temp->next_node != NULL) {

        if (temp->info.i == data_element.i && 
		temp->info.j == data_element.j) {
            return temp->info;
        }
        temp=temp->next_node;
    }
 
    if (temp->info.i == data_element.i && 
		temp->info.j == data_element.j) {

        return temp->info;
    }

    return nulinfo;
}
 
void delC(arr,n,value)
int *arr;
int *n;
int value;
{
    int i,j,k;

    k = -1;

    for (i=0; i < *n; i++) {
	if (arr[i] == value) {
	   k = i;
	}
    }

    if (k == -1) return;

    (*n)--;
    for (i=k; i < *n; i++) {
	arr[i] = arr[i+1];
    }
}

void repC(arr,n,value,nval)
int *arr;
int *n;
int value;
int nval;
{
    int i;

    for (i=0; i < *n; i++) {
	if (arr[i] == value) {
	   arr[i] = nval;
	}
    }

}

void redC(arr,n,nval)
int *arr;
int *n;
int nval;
{
    int i,j,frst,nn;


    frst = -1;
    i = 0;

    while (i < *n) {
	if (arr[i] == nval) {
	   if (frst != -1) {
		nn = (*n) - 1;
		for (j=i; j < nn; j++) {
		   arr[j] = arr[j+1];
		}
		(*n)--;
	   } else {
		frst = 0;
	   }
	}
	i++;
    }

}

void delArr(arr,n,value)
LDAT *arr;
int *n;
int value;
{
    int i;

    (*n)--;
    for (i=value; i < *n; i++) {
	arr[i] = arr[i+1];
    }
}

void prL(int *L,int N,int C1)
{
   int kk;
   for (kk=0; kk < N; kk++) {
      fprintf(stderr,"L[%d] %d\n",C1,L[kk]);
   }
}

int rd_tmpArr(tmpArr,K,L,N)
LDAT **tmpArr;
int *K;
int *L[MAXTRI];
int N[MAXTRI];
{
    int i,j;
    FILE *of;
    LDAT *tArr;
    int NN;
    int LL[1000];
    

    of = fopen("tmparr","r");

    if (of == NULL) {
	fprintf(stderr,"rd_tmpArr: Error opening file tmparr\n");
 	return(-1);
    }

    *K = 0;

    fread(K, (size_t) sizeof(int), (size_t) 1, of);
    
    tArr = (LDAT *) malloc((*K)*sizeof(LDAT));

    for (i=0; i < *K; i++) {
	fread(&tArr[i], (size_t) sizeof(LDAT), (size_t) 1, of);
    }

    *tmpArr = tArr;

    for (i=0; i < *K; i++) {
	fread(&N[i], (size_t) sizeof(int), 1, of);
	L[i] = (int *) malloc(N[i]*sizeof(int));
    }


    for (i=0; i < *K; i++) {
	fread(&LL, (size_t) sizeof(int), (size_t) N[i], of);
	for (j=0; j < N[i]; j++) {
	   L[i][j] = LL[j];
	}
    }

    fclose(of);

    return(0);
}

int Chk_NNode(int *Arr,int N,int val)
{
	int i;
	
	for (i=0; i < N; i++) 
	   if (Arr[i] == val) return(1);
	return(0);
}

void Cr_NNode(NNODE **NewNodes,int *NNewNodes,int Cnew,int C1,int C2,int mx)
{
	int i,j;

/*
fprintf(stderr,"in Cr_NNode: NNewNodes %3d Cnew %3d C1 %3d C2 %3d mx %3d\n",*NNewNodes,Cnew,C1,C2,mx);
*/
	NewNodes[*NNewNodes] = (NNODE *) malloc(sizeof(NNODE));
	NewNodes[*NNewNodes]->Num = Cnew;
	NewNodes[*NNewNodes]->Arr = (int *) malloc(sizeof(int)*1000);
	NewNodes[*NNewNodes]->CC = 0;

	if (C1 <= mx && C2 <= mx) {

	   NewNodes[*NNewNodes]->Arr[0] = C1;
	   NewNodes[*NNewNodes]->Arr[1] = C2;
	   NewNodes[*NNewNodes]->N = 2;

	} else if (C1 > mx && C2 > mx) {

	   NewNodes[*NNewNodes]->N = 0;
	   for (i=0; i < *NNewNodes; i++) {
		if (NewNodes[i] != NULL) {
		   if (NewNodes[i]->Num == C1 || NewNodes[i]->Num == C2) {
			for (j=0; j < NewNodes[i]->N ; j++) {
			   if (!Chk_NNode(NewNodes[*NNewNodes]->Arr,
				NewNodes[*NNewNodes]->N, NewNodes[i]->Arr[j])) {
			   NewNodes[*NNewNodes]->Arr[NewNodes[*NNewNodes]->N] = 
						NewNodes[i]->Arr[j];
			   NewNodes[*NNewNodes]->N++;
			   }
			}
		   }
		}
	   }

	} else if (C1 > mx && C2 <= mx) {

	   NewNodes[*NNewNodes]->Arr[0] = C2;
	   NewNodes[*NNewNodes]->N = 1;

	   for (i=0; i < *NNewNodes; i++) {
		if (NewNodes[i] != NULL) {
		   if (NewNodes[i]->Num == C1) {
			for (j=0; j < NewNodes[i]->N ; j++) {
			   NewNodes[*NNewNodes]->Arr[NewNodes[*NNewNodes]->N] = 
						NewNodes[i]->Arr[j];
			   NewNodes[*NNewNodes]->N++;
			}
		   }
		}
	   }

	} else if (C2 > mx && C1 <= mx) {

	   NewNodes[*NNewNodes]->Arr[0] = C1;
	   NewNodes[*NNewNodes]->N = 1;

	   for (i=0; i < *NNewNodes; i++) {
		if (NewNodes[i] != NULL) {
		   if (NewNodes[i]->Num == C2) {
			for (j=0; j < NewNodes[i]->N ; j++) {
			   NewNodes[*NNewNodes]->Arr[NewNodes[*NNewNodes]->N] = 
						NewNodes[i]->Arr[j];
			   NewNodes[*NNewNodes]->N++;
			}
		   }
		}
	   }

	}
	(*NNewNodes)++;
}

int Get_NNode(NNODE **NewNodes,int *NNewNodes,int Ctar,int mx)
{
	int i,j;

	for (i=0; i < *NNewNodes; i++) {
	   if (NewNodes[i] != NULL) {
		if (NewNodes[i]->Num == Ctar) return(i);
	   }
	}

	return(-1);
}

void Prt_NNode(NNODE **NewNodes,int *NNewNodes)
{
	int i,j;

	for (i=0; i < *NNewNodes; i++) {
	   if (NewNodes[i] != NULL) {
		fprintf(stderr,"New Node %3d: CC %d {\n",NewNodes[i]->Num,NewNodes[i]->CC);
		for (j=0; j < NewNodes[i]->N ; j++) 
			fprintf(stderr,"%3d",NewNodes[i]->Arr[j]);
		fprintf(stderr,"\n}\n");
	   }
	}

}

void Clus_Min_NNode(NNODE **NewNodes,int *NNewNodes)
{
	int i,j,imn;
	float emin;

	emin = 10000.0;
	imn = -1;

	for (i=0; i < *NNewNodes; i++) {
	   if (NewNodes[i] != NULL) {
	      if (NewNodes[i]->CC) {
		for (j=0; j < NewNodes[i]->N ; j++) {
		   if (TriArr[NewNodes[i]->Arr[j]] != NULL) {
		      if (TriArr[NewNodes[i]->Arr[j]]->e12 < emin) {
			emin = TriArr[NewNodes[i]->Arr[j]]->e12;
			imn  = NewNodes[i]->Arr[j];
		      }
		   }
		}
		if (imn != -1) {
		   for (j=0; j < NewNodes[i]->N ; j++) {
			if (NewNodes[i]->Arr[j] != imn) {
			   safefree((void **)&TriArr[NewNodes[i]->Arr[j]]);
			   TriArr[NewNodes[i]->Arr[j]] = NULL;
			}
		   }
		   
		}
	      }
	   }
	}

}

void Test_Linkage(N,L,K,tmpArr)
int N[MAXTRI];
int *L[MAXTRI];
int *K;
LDAT *tmpArr;
{
    if (N[0] == 0) L[0] = (int *) malloc(2*sizeof(int));
    if (N[1] == 0) L[1] = (int *) malloc(2*sizeof(int));
    if (N[2] == 0) L[2] = (int *) malloc(2*sizeof(int));

    *K = 3;
    L[0][0] = 1; L[0][1] = 2; N[0] = 2; tmpArr[0].dd = 3.0; tmpArr[0].i = 0; tmpArr[0].j = 1;
    L[1][0] = 0; L[1][1] = 2; N[1] = 2; tmpArr[1].dd = 4.0; tmpArr[1].i = 1; tmpArr[1].j = 2;
    L[2][0] = 0; L[2][1] = 1; N[2] = 2; tmpArr[2].dd = 5.0; tmpArr[2].i = 0; tmpArr[2].j = 2;

}

void CalcAllInt(int deb,int all)
{
// Calculates FlexX interaction energies of all poses: e12
    int i,j,k,ido,grpj,grpk;
    float etot;
    INCRSTRU *ligtmp;

// all = 1: calculate interaction of matching ligand points with protein
//          interaction points
//
// all = 0: calculate interaction of matching ligand points with protein
//          interaction points, but only those belonging to the fragment
//          of the triangle in TriArr
//
// The latter is a score by fragment

    e12_calculated = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   
	   if (deb) fprintf(stderr,"TriArr[%3d]:\n\n",i);

	   etot = 0.0;

	   for (j=0; j < lintp; j++) {

	      grpj = Find_Group(ligtyp[j]->type);
	      grpj = Find_Matching_Group(grpj);

	      ido = 0;

	      if (!all) {
		if (ligtyp[j]->conf != -1)  {

		   if (TriArr[i]->frags[0] == ligtyp[j]->frag[0] ||
		       TriArr[i]->frags[1] == ligtyp[j]->frag[0] ||
		       TriArr[i]->frags[2] == ligtyp[j]->frag[0]) ido = 1;
		} else {
		   if (ligtyp[j]->nfrag == 1) 
			if (TriArr[i]->frag == ligtyp[j]->frag[0]) ido = 1;
		}
	      } else {
		ido = 1;
	      }

	      if (ido) {
		for (k=0; k < nintp; k++) {
	         grpk = Find_Group(inttyp[k]->type);
		 if (grpj == grpk) {
	
			etot = etot +
			CalInt(k,j,ligtyp[j]->points,TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,deb);
		 }
		}
	      }
	   }
	   TriArr[i]->e12 = etot;
	   if (all) TriArr[i]->etot = TriArr[i]->e12 + TriArr[i]->eint;

	   if (deb) fprintf(stderr,"etot = %f\n\ne12 %.3f eint %.3f\n",
			etot,TriArr[i]->e12,TriArr[i]->eint);
	}
    }
}

void CalcAllInt_Spec(int deb,int all)
{
// Calculates FlexX interaction energies of all poses: e12
    int i,j,k,ido,grpj,grpk;
    float etot;
    INCRSTRU *ligtmp;

// all = 1: calculate interaction of matching ligand points with protein
//          interaction points
//
// all = 0: calculate interaction of matching ligand points with protein
//          interaction points, but only those belonging to the fragment
//          of the triangle in TriArr
//
// The latter is a score by fragment

    e12_calculated = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   
	   if (deb) fprintf(stderr,"TriArr[%3d]:\n\n",i);

	   etot = 0.0;

	   for (j=0; j < lintp; j++) {

	      grpj = Find_Group(ligtyp[j]->type);
	      grpj = Find_Matching_Group(grpj);

	      ido = 0;

	      if (!all) {
		if (ligtyp[j]->conf != -1)  {

		   if (TriArr[i]->frags[0] == ligtyp[j]->frag[0] ||
		       TriArr[i]->frags[1] == ligtyp[j]->frag[0] ||
		       TriArr[i]->frags[2] == ligtyp[j]->frag[0]) ido = 1;
		} else {
		   if (ligtyp[j]->nfrag == 1) 
			if (TriArr[i]->frag == ligtyp[j]->frag[0]) ido = 1;
		}
	      } else {
		ido = 1;
	      }

	      if (ido) {
		for (k=0; k < nintp; k++) {
	         grpk = Find_Group(inttyp[k]->type);
		 if (grpj == grpk) {
	
			etot = etot +
			CalInt_Spec(k,j,ligtyp[j]->points,TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,deb);
		 }
		}
	      }
	   }
	   TriArr[i]->e12 = etot;
	   if (all) TriArr[i]->etot = TriArr[i]->e12 + TriArr[i]->eint;

	   if (deb) fprintf(stderr,"etot = %f\n\ne12 %.3f eint %.3f\n",
			etot,TriArr[i]->e12,TriArr[i]->eint);
	}
    }
}

/* wrt_TriArr and rd_TriArr have not been tested, 
   they probably need more work */

void wrt_TriArr()
{
    int i,j;
    FILE *of;

    of = fopen("TriArr","w");

    fwrite(&ntris, (size_t) sizeof(int), (size_t) 1, of);

    for (i=0; i < ntris; i++) {
	fwrite(TriArr[i], (size_t) sizeof(TRISTRU), (size_t) 1, of);
    }

    fwrite(&ndocka, (size_t) sizeof(int), (size_t) 1, of);

    for (i=0; i < ntris; i++) {
	fwrite(TriArr[i]->coo, (size_t) sizeof(double)*ndocka*3, (size_t) 1, of);
    }

    fclose(of);
}

void rd_TriArr()
{
    int i,j;
    FILE *of;

    of = fopen("TriArr","r");

    fread(&ntris, (size_t) sizeof(int), (size_t) 1, of);

    for (i=0; i < ntris; i++) {
	TriAll(&TriArr[i]);
	fread(TriArr[i], (size_t) sizeof(TRISTRU), (size_t) 1, of);
    }

    fread(&ndocka, (size_t) sizeof(int), (size_t) 1, of);

    for (i=0; i < ntris; i++) {
	TriArr[i]->coo = (double *) malloc(sizeof(double)*ndocka*3);
	fread(TriArr[i]->coo, (size_t) sizeof(double)*ndocka*3, (size_t) 1, of);
    }

    fclose(of);
}

void wrt_tmpArr(tmpArr,K,L,N)
LDAT *tmpArr;
int K;
int *L[MAXTRI];
int N[MAXTRI];
{
    int i,j;
    FILE *of;
    int LL[1000];

    of = fopen("tmparr","w");

    
    fwrite(&K, (size_t) sizeof(int), (size_t) 1, of);

    for (i=0; i < K; i++) {
	fwrite(&tmpArr[i], (size_t) sizeof(LDAT), (size_t) 1, of);
    }

    for (i=0; i < K; i++) {
	fwrite(&N[i], (size_t) sizeof(int), 1, of);
    }

    for (i=0; i < K; i++) {
	for (j=0; j < N[i]; j++) {
	   LL[j] = L[i][j];
	}
	fwrite(&LL, (size_t) sizeof(int), (size_t) N[i], of);
    }

    fclose(of);
}

#define MAXNNODE 10000

void Linkage_List(float clusrms)
{
    int i,j,k,K,l,n,iN,nt,frst,inm;
    double dd,ddthresh,*DDc1,*DDc2;
    LDAT *tmpArr;
    LDAT info,info_tmp;
    NNODE *NewNodes[MAXNNODE];
    int tmpi[MAXTRI],N[MAXTRI],*L[MAXTRI];
    int NN1,NN2,NARR,BTEL,NDEL,MXARR;
    int *L1,*L2,NNewNodes;
    int C1,C2,Ci,Cj,Cnew,stat,istat,mx,inode,inode1,inode2,OldN;
    node *p,*delnode,**BARR,**DELARR;

    ddthresh = clusrms/toangs;
    NNewNodes = 0;

    for (i=0; i < MAXNNODE; i++) {
	NewNodes[i] = NULL;
    }

    K = 0;
    NDEL = 0;

    n = ntris;

    if (n == 1) return;

    nt = (n*(n+1))/2;

    tmpArr = (LDAT *) malloc(nt*sizeof(LDAT));

    for (i=0; i < nt; i++) {
	tmpArr[i].stat = -1;
	tmpArr[i].Arr = NULL;
	tmpArr[i].N = 0;
    }

    k = -1;
    for (i=0; i < n; i++) {
	inm = 0;
	for (j=0; j < n; j++) {
	   if (TriArr[i] != NULL && TriArr[j] != NULL) {
	      if (TriArr[i]->coo == NULL || TriArr[j]->coo == NULL) {
		 dd = 1.0;
	      } else {
	         dd = dst(TriArr[i],TriArr[j]);
	      }
	      if (j > i) {
		if (dd <= 0.000001) {
	    	   TriCooSafeFree(j);
	    	   TriSafeFreeTxt(j,"Linkage_list","Reason: dist < 0.000001");
		   for (l=0; l < j; l++) {
			if (N[l] > 0) {
			   delC(L[l],&N[l],j);
			   delC(tmpi,&inm,j);
			}
		   }
		   for (l=0; l < k+1; l++) 
			if (tmpArr[l].i == j || tmpArr[l].j == j) 
			   tmpArr[l].dd = -1.0; 
		} else if (dd < ddthresh) {
		   k++; 
		   if (nt > k) {
			tmpArr[k].dd = dd;
			tmpArr[k].i = i;
			tmpArr[k].j = j;
			tmpArr[k].stat = -1;
		   } else {
			fprintf(stderr,"k %d > nt %d\n",k,nt);
		   }
		   tmpi[inm] = j;
		   inm++;
		}
	      } else if (j == i) {
	      } else {
		if (dd >  0.000001 && dd < ddthresh) {
		   tmpi[inm] = j;
		   inm++;
		}
	      }
	   }
	}

	if (inm > 0) {
	   N[i] = inm;
	   qsort(tmpi, inm, sizeof(int), SI);
	   L[i] = (int *) malloc((k+1)*sizeof(int));
	   for (l=0; l < inm; l++)  L[i][l] = tmpi[l];
	} else {
	   N[i] = 0;
	   L[i] = NULL;
	}
    }

    K = k + 1;

if (debugdck) fprintf(stderr,"0 K %d\n",K);

    for (i=0; i < k+1; i++) 
	while (tmpArr[i].dd == -1.0 && K > 0) delArr(tmpArr,&K,i);

if (debugdck) fprintf(stderr,"aft delArr K %d\n",K);

    if (!K) return;

    if (0) wrt_tmpArr(tmpArr,K,L,N);

    if (0) Test_Linkage(N,L,&K,tmpArr);

    CalcAllInt(0,0);

    qsort((LDAT *) tmpArr, K, sizeof(LDAT), cmpldat);

if (debugdck) fprintf(stderr,"K %d\n",K);
    MXARR = K + 1000;

    BARR = (node **) malloc(MXARR*sizeof(node *));
    DELARR = (node **) malloc(MXARR*sizeof(node *));

    frst = -1;

    for (i=0; i < K; i++) {
	if ( frst == -1) {
	   begin = addtoemptylist(begin,tmpArr[i]);
	   frst = 0;
	} else {
	   begin = addatendlist(begin,tmpArr[i]);
	}
    }

    set_List(begin,BARR,&NARR,MXARR);
    mx = max_List(begin);

    p = BARR[0]; BTEL = 0;
    Cnew = mx + 1;

    delnode = NULL;

    while (p != NULL) {

	if (debugdck) dsply_List(begin);

	C1 = p->info.i;
	C2 = p->info.j;

	if (debugdck) {
fprintf(stderr,"Cluster candidate C1 %d C2 %d N[C1] %d N[C2] %d\n\n",C1,C2,N[C1],N[C2]);
prL(L[C1],N[C1],C1);
fprintf(stderr,"\n");
prL(L[C2],N[C2],C2);
fprintf(stderr,"\n");
	}

	delC(L[C1],&N[C1],C2);
	delC(L[C2],&N[C2],C1);

	stat = p->info.stat;
	iN = p->info.N;

	begin = deletenode(begin,delnode,&p->info,BARR,&NARR);
	p = dlnode(p,&p->info);
	Add2Delarr(delnode,DELARR,&NDEL,MXARR);

	N[Cnew] = N[C1] + N[C2];
	L[Cnew] = (int *) malloc(K*sizeof(int));
	N[Cnew] = 0;

	NN1 = N[C1];
	NN2 = N[C2];
	L1 = (int *) malloc(NN1*sizeof(int));
	L2 = (int *) malloc(NN2*sizeof(int));
	DDc1 = (double *) malloc(NN1*sizeof(double));
	DDc2 = (double *) malloc(NN2*sizeof(double));

	for (Ci=0; Ci < NN1; Ci++) L1[Ci] = L[C1][Ci];
	for (Cj=0; Cj < NN2; Cj++) L2[Cj] = L[C2][Cj];
	
	if (Get_NNode(NewNodes,&NNewNodes,Cnew,mx) == -1)
		Cr_NNode(NewNodes,&NNewNodes,Cnew,C1,C2,mx);

	if (stat == -1) {
	   info.stat = 1;
	   info.Arr = (int *) malloc(sizeof(int)*1000);
	   info.Arr[0] = C1;
	   info.Arr[1] = C2;
	   info.N = 2;
	} else {
	   info.stat = stat + 1;
	   info.N = 0;

	   if (C1 > mx) {
		inode1 = Get_NNode(NewNodes,&NNewNodes,C1,mx);
		if (inode1 != -1) {
	   	    for (i=0; i < NewNodes[inode1]->N; i++) {
			if (!Chk_NNode(info.Arr,info.N,
				NewNodes[inode1]->Arr[i])) {
			   info.Arr[info.N] = NewNodes[inode1]->Arr[i];
			   info.N++;
			}
		    }
		}
	   } else {
		info.Arr[info.N] = C1;
		info.N++;
	   }

  	   if (C2 > mx) {
		inode2 = Get_NNode(NewNodes,&NNewNodes,C2,mx);
		if (inode2 != -1) {
	   	   for (i=0; i < NewNodes[inode2]->N; i++) {
			if (!Chk_NNode(info.Arr,info.N,
				NewNodes[inode2]->Arr[i])) {
			   info.Arr[info.N] = NewNodes[inode2]->Arr[i];
			   info.N++;
			}
		   }
		}
	   } else {
		info.Arr[info.N] = C2;
		info.N++;
	   }
	}

	set_List(begin,BARR,&NARR,MXARR);
	if (N[C1] == 0 && N[C2] == 0) NewNodes[NNewNodes-1]->CC = 1;

	if (0) Prt_NNode(NewNodes,&NNewNodes);

	if (NARR == 0) goto NEXT;

	OldN = info.N;

	while (N[C1] != 0 || N[C2] != 0) {

	   for (Ci=0; Ci < NN1; Ci++) {

	      if (L1[Ci] < C1) {
		      info.i = L1[Ci]; info.j = C1;
	      } else {
		      info.i = C1; info.j = L1[Ci];
	      }
	      info_tmp = get_info(begin,info);
	      DDc1[Ci] = info_tmp.dd;


	      if (!Chk_NNode(L2,NN2,L1[Ci])) {

		   if (L1[Ci] < C1) {
		      info.i = L1[Ci]; info.j = C1; 
		   } else {
		      info.i = C1; info.j = L1[Ci];
		   }
		   info_tmp = get_info(begin,info);

		   if (! (info_tmp.i == -1 && info_tmp.j == -1) ) {

		      info.i = L1[Ci]; info.j = Cnew; 
		      info.dd = DDc1[Ci];
		      info.N = OldN;

		      if (info.i > mx) {
			inode = Get_NNode(NewNodes,&NNewNodes,info.i,mx);
			if (inode != -1) {
	   		   for (i=0; i < NewNodes[inode]->N; i++) {
				info.Arr[info.N] = NewNodes[inode]->Arr[i];
				info.N++;
			   }
			}
		      }

		      begin = insertdd(begin,BARR,&NARR,info);
		      set_List(begin,BARR,&NARR,MXARR);
		      info.N = OldN;

		      L[L1[Ci]][N[L1[Ci]]] = Cnew; 
		      N[L1[Ci]]++;

		      L[Cnew][N[Cnew]] = L1[Ci]; N[Cnew]++;

		      delC(L[C1],&N[C1],L1[Ci]);

		      delC(L[Ci],&N[Ci],C1);
		      delC(L[Ci],&N[Ci],C2);
		   }
	      }

	      if (L1[Ci] < C1) {
		      info.i = L1[Ci]; info.j = C1;
	      } else {
		      info.i = C1; info.j = L1[Ci];
	      }
	      begin = deletenode(begin,delnode,&info,BARR,&NARR);
	      Add2Delarr(delnode,DELARR,&NDEL,MXARR);

	   }

	   for (Cj=0; Cj < NN2; Cj++) {

		if (L2[Cj] < C2) {
		      info.i = L2[Cj]; info.j = C2;
		} else {
		      info.i = C2; info.j = L2[Cj];
		}
	        info_tmp = get_info(begin,info);
	        DDc2[Cj] = info_tmp.dd;

		if (!Chk_NNode(L1,NN1,L2[Cj])) {

		   if (L2[Cj] < C2) {
		      info.i = L2[Cj]; info.j = C2; 
		   } else {
		      info.i = C2;     info.j = L2[Cj];
		   }
		   info_tmp = get_info(begin,info);

		   if (! (info_tmp.i == -1 && info_tmp.j == -1)) { 

		      info.i = L2[Cj]; info.j = Cnew; 
		      info.dd = DDc2[Cj];
		      info.N = OldN;

		      if (info.i > mx) {
			inode = Get_NNode(NewNodes,&NNewNodes,info.i,mx);
			if (inode != -1) {
	   		   for (i=0; i < NewNodes[inode]->N; i++) {
				info.Arr[info.N] = NewNodes[inode]->Arr[i];
				info.N++;
			   }
			}
		      }

		      begin = insertdd(begin,BARR,&NARR,info);
		      set_List(begin,BARR,&NARR,MXARR);
		      info.N = OldN;

		      L[L2[Cj]][N[L2[Cj]]] = Cnew; 
		      N[L2[Cj]]++;

		      L[Cnew][N[Cnew]] = L2[Cj]; N[Cnew]++;

		      delC(L[C2],&N[C2],L2[Cj]);

		      delC(L[Cj],&N[Cj],C1);
		      delC(L[Cj],&N[Cj],C2);
		   }
		}

		if (L2[Cj] < C2) {
		      info.i = L2[Cj]; info.j = C2;
		} else {
		      info.i = C2; info.j = L2[Cj];
		}
		begin = deletenode(begin,delnode,&info,BARR,&NARR);
	        Add2Delarr(delnode,DELARR,&NDEL,MXARR);

	   }

	   for (Ci=0; Ci < NN1; Ci++) {
	      delC(L[Ci],&N[Ci],C1);
	      for (Cj=0; Cj < NN2; Cj++) {

		delC(L[Cj],&N[Cj],C2);

		if (L1[Ci] < L2[Cj]) {

		   delC(L[C1],&N[C1],L1[Ci]);

		} else if (L1[Ci] > L2[Cj]) {

		   delC(L[C2],&N[C2],L2[Cj]);

		} else if (L1[Ci] == L2[Cj]) {


		   if (L1[Ci] < C1) {
		      info.i = L1[Ci]; info.j = C1;
		   } else {
		      info.i = C1; info.j = L1[Ci];
		   }
		   begin = deletenode(begin,delnode,&info,BARR,&NARR);
	           Add2Delarr(delnode,DELARR,&NDEL,MXARR);

		   if (L1[Ci] < C2) {
		      info.i = L1[Ci]; info.j = C2;
		   } else {
		      info.i = C2; info.j = L1[Ci];
		   }
		   begin = deletenode(begin,delnode,&info,BARR,&NARR);
	           Add2Delarr(delnode,DELARR,&NDEL,MXARR);

		   info.i = L1[Ci]; info.j = Cnew; 
		   info.dd = MAXI(DDc1[Ci],DDc2[Cj]);

		   info.N = OldN;

		   if (info.i > mx) {
			inode = Get_NNode(NewNodes,&NNewNodes,info.i,mx);
			if (inode != -1) {
	   		   for (i=0; i < NewNodes[inode]->N; i++) {
				info.Arr[info.N] = NewNodes[inode]->Arr[i];
				info.N++;
			   }
			}
		   }


		   begin = insertdd(begin,BARR,&NARR,info);
		   info.N = OldN;
		   set_List(begin,BARR,&NARR,MXARR);

		   L[L1[Ci]][N[L1[Ci]]] = Cnew; 
		   N[L1[Ci]]++;

		   L[Cnew][N[Cnew]] = L1[Ci]; N[Cnew]++;

		   delC(L[C1],&N[C1],L1[Ci]);
		   delC(L[C2],&N[C2],L2[Cj]);

		   delC(L[Ci],&N[Ci],C1);
		   delC(L[Cj],&N[Cj],C2);

		}
	      }

	   }
	}

	for (i=0; i < Cnew; i++) {
	   repC(L[i],&N[i],C1,Cnew);
	   repC(L[i],&N[i],C2,Cnew);
	   redC(L[i],&N[i],Cnew);
	}

	for (j=0; j < Cnew+1; j++) {
	   for (i=0; i < Cnew; i++) {
		redC(L[i],&N[i],j);
	   }
	}

	replc_List(begin,C1,Cnew);
	replc_List(begin,C2,Cnew);
	replc_List(p,C1,Cnew);
	replc_List(p,C2,Cnew);

	Cnew++; BTEL++;
	if (BTEL >= NARR) {
	   if (NARR == 0) goto NEXT;
	   BTEL = 0;
	}
	p = BARR[BTEL];
	safefree((void **)&L1);
	safefree((void **)&L2);
	L1 = NULL;
	L2 = NULL;
    }

NEXT:
    Clus_Min_NNode(NewNodes,&NNewNodes);

    return;
	
}

static float rndf(float num)
{
    float integer = ceilf(num);
    if (num > 0)
        return integer - num > 0.5f ? integer - 1.0f : integer;
    return integer - num >= 0.5f ? integer - 1.0f : integer;
}

int issCOO(iat,io1,io2)
int iat;
int *io1;
int *io2;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (xyzp->ianz[iat] != 6) return 0;

    *io1 = -1;
    *io2 = -1;
    io = 0;
    ic = 0;
    ih = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8)  {
		io++;
		if (io == 1) *io1 = la-1;
		if (io == 2) *io2 = la-1;
	   }
	   if (xyzp->ianz[la-1] == 6) ic++;
	   if (xyzp->ianz[la-1] == 1) ih++;
	}
    }

    if (io == 2 && ic == 1 && ih == 0) return 1;
    return 0;
}

int isAZIDE(iat)
int iat;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 7 && isANY(xyzp->ityp[iat],N2ar,2))) return 0;
    
    n = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 7 && 
		isANY(xyzp->ityp[la-1],Nany,7)) {
		n++;
	   }
	}
    }
    if (n == 2) return 1;
    return 0;
}

int isNaryl(iat,io1,io2)
int iat;
int *io1;
int *io2;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 7 && isANY(xyzp->ityp[iat],N2ar,2) && xc == 2)) return 0;
    
    n = 0;
    *io1 = -1;
    *io2 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ianz[la-1],GrpR,6)) {
		n++;
		if (n == 1) *io1 = la - 1;
		if (n == 2) *io2 = la - 1;
	   }
	}
    }
    if (n == 2) return 1;
    return 0;
}

int isNamino(iat,io1,io2,io3)
int iat;
int *io1;
int *io2;
int *io3;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 7 && xyzp->ityp[iat] == 10 && xc == 3)) return 0;
    
    n = 0;
    *io1 = -1;
    *io2 = -1;
    *io3 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ianz[la-1],GrpRH,7)) {
		n++;
		if (n == 1) *io1 = la - 1;
		if (n == 2) *io2 = la - 1;
		if (n == 3) *io3 = la - 1;
	   }
	}
    }
    if (n == 3) return 1;
    return 0;
}

int isOH(iat,io1)
int iat;
int *io1;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 8 && isANY(xyzp->ityp[iat],Oany,3) && xc == 2)) 
		return 0;
    
    n = 0;
    *io1 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 1) {
		n++;
		*io1 = la - 1;
	   } else {
		if (isANY(xyzp->ianz[la-1],GrpRH,7)) n++;
	   }
	}
    }
    if (n == 2) return 1;
    return 0;
}

int isNT(iat,io1)
int iat;
int *io1;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 7 && isANY(xyzp->ityp[iat],Nany,7) && xc == 1)) return 0;
    
    n = 0;
    *io1 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ianz[la-1],GrpRH,7)) {
		n++;
		if (n == 1) *io1 = la - 1;
	   }
	}
    }
    if (n == 1) return 1;
    return 0;
}

int isSNH(iat,io1,io2)
int iat;
int *io1;
int *io2;
{
    int xc,io,ic,ih,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 7 && isANY(xyzp->ityp[iat],Nany,7) && xc == 2)) return 0;
    
    n = 0;
    ih = 0;
    *io1 = -1;
    *io2 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ityp[la-1],Sany,4)) {
		n++;
		if (n == 1) *io1 = la - 1;
	   }
	   if (xyzp->ianz[la-1] == 1) {
		ih++;
		if (ih == 1) *io2 = la - 1;
	   }
	}
    }
    if (n == 1 && ih == 1) return 1;
    return 0;
}

int isAMID(iat,np,io2)
int iat;
int *np;
int *io2;
{
    int xc,xn,i,k,l,la,ll,lla,no,nn,nh;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 6 && xyzp->ityp[iat] == 6 && xc == 3)) return 0;
    
    no = 0; nn = 0; nh = 0;
    *np = -1;
    *io2 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && xyzp->ityp[la-1] == 18) {
		no++;
		if (no == 1) *io2 = la - 1;
	   }
	   if (xyzp->ianz[la-1] == 7 && 
		(xyzp->ityp[la-1] == 14 || xyzp->ityp[la-1] == 15)) {
		nn++;
		if (nn == 1) *np = la - 1;
		xn = xyzp->iconn[(la-1)*(MXCON+1)];
		for (i=0; i < xn; i++) {
		   ll = xyzp->iconn[(la-1)*(MXCON+1)+i+1];
		   lla = abs(ll);
		   if (lla > 0) {
	   		if (xyzp->ianz[lla-1] == 1) nh++;
		   }
		}
	   }
	}
    }
    if (no == 1 && nn == 1 && nh >= 1) return 1;
    return 0;
}

int isRF(iat,io1)
int iat;
int *io1;
{
    int xc,k,l,la,n;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 9 && xc == 1)) return 0;
    
    n = 0;
    *io1 = -1;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ianz[la-1],GrpR,6)) {
		n++;
		if (n == 1) *io1 = la - 1;
	   }
	}
    }
    if (n == 1) return 1;
    return 0;
}

int isCO(iat,io1)
int iat;
int *io1;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 6 && isANY(xyzp->ityp[iat],C2ar,2))) return 0;

    *io1 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && 
		xyzp->iconn[(la-1)*(MXCON+1)] == 1) {
		if (xyzp->ityp[la-1] == 18)  {
		   io++;
		   if (io == 1) *io1 = la-1;
		}
	   }
	}
    }

    if (io == 1) return 1;
    return 0;
}

int isCOmin(iat,io1)
int iat;
int *io1;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    if (!(xyzp->ianz[iat] == 6 && isANY(xyzp->ityp[iat],Cany,4))) return 0;

    *io1 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && 
		xyzp->iconn[(la-1)*(MXCON+1)] == 1) {
		if (xyzp->ityp[la-1] == 17)  {
		   io++;
		   if (io == 1) *io1 = la-1;
		}
	   }
	}
    }

    if (io == 1) return 1;
    return 0;
}

int isSO(iat,io1,io2)
int iat;
int *io1;
int *io2;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 16 || isANY(xyzp->ityp[iat],Sany,4)) return 0;

    *io1 = -1;
    *io2 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && xyzp->iconn[(la-1)*(MXCON+1)] == 1)  {
		if (isANY(xyzp->ityp[la-1],Oany,3)) {
		io++;
		if (io == 1) *io1 = la-1;
		if (io == 2) *io2 = la-1;
		}
	   }
	}
    }

    if (io == 1 || io == 2) return 1;
    return 0;
}

int isCH3R(iat)
int iat;
{
    int xc,i,ir,ih,k,l,la;

    if (xyzp->ianz[iat] != 6 || xyzp->ityp[iat] != 5) return 0;

    xc = xyzp->iconn[iat*(MXCON+1)];

    ih = 0;
    ir = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 1) ih++;
	   if (isANY(xyzp->ianz[la-1],GrpR,6)) ir++;
	}
    }

    if (ih == 3 && ir == 1) return 1;
    if (ih == 2 && ir == 2) return 2;
    if (ih == 1 && ir == 3) return 3;
    return 0;
}

int isS3(iat)
int iat;
{

    if (xyzp->ianz[iat] == 16 && xyzp->ityp[iat] == 22) return 1;

    return 0;
}

int isCarR(iat)
int iat;
{
    int xc,i,ir,ih,k,l,la;

    if (xyzp->ianz[iat] != 6 || xyzp->ityp[iat] != 8) return 0;

    xc = xyzp->iconn[iat*(MXCON+1)];

    ih = 0;
    ir = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 1) ih++;
	   if (isANY(xyzp->ianz[la-1],GrpR,6)) ir++;
	}
    }

    if (ih == 0 && ir == 3) return 1;
    if (ih == 1 && ir == 2) return 2;
    return 0;
}

int isPO(iat,io1,io2,io3)
int iat;
int *io1;
int *io2;
int *io3;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 15 || xyzp->ityp[iat] != 26) return 0;

    *io1 = -1;
    *io2 = -1;
    *io3 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && xyzp->iconn[(la-1)*(MXCON+1)] == 1)  {
		if (isANY(xyzp->ityp[la-1],Oany,3)) {
		io++;
		if (io == 1) *io1 = la-1;
		if (io == 2) *io2 = la-1;
		if (io == 3) *io3 = la-1;
		}
	   }
	}
    }

    if (io >1 && io <= 3) return 1;
    return 0;
}

int isNO2(iat,io1,io2)
int iat;
int *io1;
int *io2;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 7 || !isANY(xyzp->ityp[iat],N2ar,2)) return 0;

    *io1 = -1;
    *io2 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && xyzp->iconn[(la-1)*(MXCON+1)] == 1)  {
		if (xyzp->ityp[la-1] == 18) {
		io++;
		if (io == 1) *io1 = la-1;
		if (io == 2) *io2 = la-1;
		}
	   }
	}
    }

    if (io == 2) return 1;
    return 0;
}

int isNO(iat,io1)
int iat;
int *io1;
{
    int xc,io,ic,ih,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 7 || !isANY(xyzp->ityp[iat],Nany,7)) return 0;

    *io1 = -1;
    io = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 8 && xyzp->iconn[(la-1)*(MXCON+1)] == 1)  {
		if (isANY(xyzp->ityp[la-1],Oany,3)) {
		io++;
		if (io == 1) *io1 = la-1;
		}
	   }
	}
    }

    if (io == 1) return 1;
    return 0;
}

int isCOH(iat,ic,ih,ic2,it)
int iat;
int *ic;
int *ih;
int *ic2;
int *it;
{
    int xc,icc,ihh,k,l,la,ll,lla,kk,xxc;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 8 || xyzp->ityp[iat] != 17) return 0;

    *ic  = -1;
    *ih  = -1;
    *ic2 = -1;
    icc = 0;
    ihh = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (l > 0) {
	   if (xyzp->ianz[la-1] == 1)  {
		ihh++;
		if (ihh == 1) *ih = la-1;
	   }
	}
    }

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (l > 0) {
	   *it = xyzp->ityp[la-1];
// 5 = C.3 6 = C.2 8 = C.ar
	   if (xyzp->ianz[la-1] == 6 && (*it == 5 || *it == 6 || *it == 8))  {
		icc++;
		if (icc == 1) *ic = la-1;

// we must now look connections to the carbon 

		xxc = xyzp->iconn[(la-1)*(MXCON+1)];
		for (kk=0; kk < xxc; kk++) {
		  ll = xyzp->iconn[(la-1)*(MXCON+1)+kk+1];
		  lla = abs(ll);
		  if (xyzp->ianz[lla-1] == 6) {
			*ic2 = lla-1;
			break;
		  }
		}
	   }
	}
    }
    if (icc == 1 && ihh == 1) return 1;
    return 0;
}

int isC3OH(iat,ic,ih)
int iat;
int *ic;
int *ih;
{
    int xc,icc,ihh,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 8 || xyzp->ityp[iat] != 17) return 0;

    *ic = -1;
    *ih = -1;
    icc = 0;
    ihh = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 6 && xyzp->ityp[la-1] == 5)  {
		icc++;
		if (icc == 1) *ic = la-1;
	   }
	   if (xyzp->ianz[la-1] == 1)  {
		ihh++;
		if (ihh == 1) *ih = la-1;
	   }
	}
    }

    if (icc == 1 && ihh == 1) return 1;
    return 0;
}

int isC2OH(iat,ic,ih)
int iat;
int *ic;
int *ih;
{
    int xc,icc,ihh,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 8 || xyzp->ityp[iat] != 17) return 0;

    *ic = -1;
    *ih = -1;
    icc = 0;
    ihh = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (xyzp->ianz[la-1] == 6 && 
		(xyzp->ityp[la-1] == 6 || xyzp->ityp[la-1] == 8))  {
		icc++;
		if (icc == 1) *ic = la-1;
	   }
	   if (xyzp->ianz[la-1] == 1)  {
		ihh++;
		if (ihh == 1) *ih = la-1;
	   }
	}
    }

    if (icc == 1 && ihh == 1) return 1;
    return 0;
}

int isCOC(iat,ic1,ic2)
int iat;
int *ic1;
int *ic2;
{
    int xc,icc,ihh,k,l,la;

    xc = xyzp->iconn[iat*(MXCON+1)];
    
    if (xyzp->ianz[iat] != 8 || xyzp->ityp[iat] != 17) return 0;

    *ic1 = -1;
    *ic2 = -1;
    icc = 0;

    for (k=0; k < xc; k++) {
	l = xyzp->iconn[iat*(MXCON+1)+k+1];
	la = abs(l);
	if (la > 0) {
	   if (isANY(xyzp->ianz[la-1],GrpR,6)) {
		icc++;
		if (icc == 1) *ic1 = la-1;
		if (icc == 2) *ic2 = la-1;
	   }
	}
    }

    if (icc == 2) return 1;
    return 0;
}

void isC3RNG(C,iring,oring,n)
COOSTRU *C;
int iring[6];
int oring[6];
int n;
{
   int i,j,k;

   for (i=0; i < n; i++) {
	oring[i] = 0;
	if (isANY(C->ityp[iring[i]],C2ar,2)) {
	   for (j=0; j < C->iconn[(iring[i])*(MXCON+1)]; j++) {
	      k = C->iconn[(iring[i])*(MXCON+1)+1+j]-1;
	      if (C->ianz[k] == 1) oring[i] = 1;
	   }
	}
   }
}

void ReORNG(C,iring,n)
COOSTRU *C;
int iring[6];
int n;
{
   int i,ii,j,k,jring[6];

   for (i=0; i < n; i++) {
	if (C->lwrit[iring[i]] == 0) {
	   k = i;
	   break;
	}
   }

   
   j = 0;
   for (i=k; i < k+n; i++) {
	ii = i;
	if (i > n-1) ii =  i - n;
	jring[j] = iring[ii];
	j++;
   }
   for (i=0; i < n; i++) iring[i] = jring[i];
}

int isDON(typ)
int typ;
{
   int i,ret;

   ret = 0;

   for (i=0; i < 9; i++) if (typ == DONG[i]) ret = 1;
 
   return(ret);
}

int isANY(ele,arr,n)
int ele;
int *arr;
int n;

{
   int i,ret;

   ret = 0;

   for (i=0; i < n; i++) if (ele == arr[i]) ret = 1;
 
   return(ret);
}

void RNGmin1(iring,n)
int iring[6];
int n;
{
   int i;
  
   for (i=0; i < n; i++) {
	iring[i] = iring[i] - 1;
   }
}

void RNGput(iring,n,ival)
int iring[6];
int n;
int ival;
{
   int i;

   for (i=0; i < n; i++) {
	if (singleb.jrng[iring[i]] == 0) {
	   singleb.jrng[iring[i]] = ival;
	}
   }
}

int Has_Con(C,ele,ian,iele)
COOSTRU *C;
int ele;
int ian;
int iele[3];
{
   int i,j,k,ret;

   ret = 0;
   k = -1;
   for (i=0; i < 4; i++) iele[i] = -1;

   for (i=0; i < C->iconn[(ele)*(MXCON+1)]; i++) {
	j = C->iconn[(ele)*(MXCON+1)+1+i]-1;
	if (C->ianz[j] == ian) {
	   ret = 1;
	   k++;
	   iele[k] = j;
	}
   }
 
   return(ret);
}

void ReleaseLig()
{
   int i;

   for (i=0; i<lintp; i++) {
	safefree((void **)&ligtyp[i]);
   }
}

void AllInt(C,indx,at1,at2,at3,at4,n,grp1,grp2,coo,iconf,link)
COOSTRU *C;
int *indx;
int at1;
int at2;
int at3;
int at4;
int n;
int grp1;
AREASTRU grp2;
double *coo;
int iconf;
int link;
{
   int j;
   INCRSTRU tmptyp;

   ligtyp[*indx] =  (INCRSTRU *) malloc((sizeof tmptyp));
   memcpy(ligtyp[*indx],&IncrIni,sizeof(INCRSTRU));

   for (j=0; j<3; j++) {
	switch(n) {
	case 1:
		ligtyp[*indx]->c[0][j] = coo[(at1)*3+j];
		ligtyp[*indx]->atom[0] = at1;
		ligtyp[*indx]->n = 1;
		break;
	case 2:
		ligtyp[*indx]->c[0][j] = coo[(at1)*3+j];
		ligtyp[*indx]->c[1][j] = coo[(at2)*3+j];
		ligtyp[*indx]->atom[0] = at1;
		ligtyp[*indx]->atom[1] = at2;
		ligtyp[*indx]->n = 2;
		break;
	case 3:
		ligtyp[*indx]->c[0][j] = coo[(at1)*3+j];
		ligtyp[*indx]->c[1][j] = coo[(at2)*3+j];
		ligtyp[*indx]->c[2][j] = coo[(at3)*3+j];
		ligtyp[*indx]->atom[0] = at1;
		ligtyp[*indx]->atom[1] = at2;
		ligtyp[*indx]->atom[2] = at3;
		ligtyp[*indx]->n = 3;
		break;
	case 4:
		ligtyp[*indx]->c[0][j] = coo[(at1)*3+j];
		ligtyp[*indx]->c[1][j] = coo[(at2)*3+j];
		ligtyp[*indx]->c[2][j] = coo[(at3)*3+j];
		ligtyp[*indx]->c[3][j] = coo[(at4)*3+j];
		ligtyp[*indx]->atom[0] = at1;
		ligtyp[*indx]->atom[1] = at2;
		ligtyp[*indx]->atom[2] = at3;
		ligtyp[*indx]->atom[3] = at4;
		ligtyp[*indx]->n = 4;
		break;
	default:
		break;
	}
   }
   ligtyp[*indx]->type = grp1;
   ligtyp[*indx]->area = grp2;

if (grp2.iden == 3) {
	ANHP[nnhp] = *indx;
	nnhp++;
}
if (grp2.iden == 1) {
	ACO[nco] = *indx;
	nco++;
}
   ligtyp[*indx]->conf = iconf;
   ligtyp[*indx]->link = link;
   ligtyp[*indx]->ohlig = 0;
   ligtyp[*indx]->ohsame = 0;

   cal_area(ligtyp[*indx]);

   (*indx)++;
}

void FrgInt(indx)
int indx;
{
// Set members frag and nfrag of structure ligtyp (INCRSTRU)

   int fragi[4],at1,at2,at3,at4,f0n1,f0n2,f0n3,f1n2,f1n3,f2n3;

   at1 = ligtyp[indx]->atom[0];
   at2 = ligtyp[indx]->atom[1];
   at3 = ligtyp[indx]->atom[2];
   at4 = ligtyp[indx]->atom[3];

   switch(ligtyp[indx]->n) {
	case 1:
		ligtyp[indx]->frag[0] = singleb.ifrg[at1];
		ligtyp[indx]->nfrag = 1;
		break;
	case 2:
		fragi[0] = singleb.ifrg[at1];
		fragi[1] = singleb.ifrg[at2];

		ligtyp[indx]->frag[0] = fragi[0];

		if (fragi[0] != fragi[1]) {
		   ligtyp[indx]->frag[1] = fragi[1];
		   ligtyp[indx]->nfrag = 2;
		} else {
		   ligtyp[indx]->nfrag = 1;
		}
		break;
	case 3:
		fragi[0] = singleb.ifrg[at1];
		fragi[1] = singleb.ifrg[at2];
		fragi[2] = singleb.ifrg[at3];

		ligtyp[indx]->frag[0] = fragi[0];

		if (fragi[0] != fragi[1]) {

		   ligtyp[indx]->frag[1] = fragi[1];

		   if (fragi[0] != fragi[2]) {
			if (fragi[1] != fragi[2]) {
			   ligtyp[indx]->frag[2] = fragi[2];
			   ligtyp[indx]->nfrag = 3;
			} else {
			   ligtyp[indx]->nfrag = 2;
			}
		   } else {
			ligtyp[indx]->nfrag = 2;
		   }

		} else {

		   if (fragi[0] != fragi[2]) {
			ligtyp[indx]->frag[1] = fragi[2];
			ligtyp[indx]->nfrag = 2;
		   } else {
			ligtyp[indx]->nfrag = 1;
		   }

		}
		break;
	case 4:

		fragi[0] = singleb.ifrg[at1];
		fragi[1] = singleb.ifrg[at2];
		fragi[2] = singleb.ifrg[at3];
		fragi[3] = singleb.ifrg[at4];

		f0n1 = 0; if (fragi[0] == fragi[1]) f0n1 = 1;
		f0n2 = 0; if (fragi[0] == fragi[2]) f0n2 = 1;
		f0n3 = 0; if (fragi[0] == fragi[3]) f0n3 = 1;
		f1n2 = 0; if (fragi[1] == fragi[2]) f1n2 = 1;
		f1n3 = 0; if (fragi[1] == fragi[3]) f1n3 = 1;
		f2n3 = 0; if (fragi[2] == fragi[3]) f2n3 = 1;

		if (f0n1 && f0n2 && f0n3) {
// all four atoms are from the same fragment

		   ligtyp[indx]->frag[0] = fragi[0];
		   ligtyp[indx]->nfrag = 1;

		} else if ((f0n1 && f1n2 && !f0n3) || 
		   ((f1n2 && f2n3 && !f0n1) || (f2n3 && f0n3 && !f1n2)) ||
			   (f0n1 && f1n3 && !f2n3)) {

// three atoms are from the same fragment, ONE is NOT: two fragments

		   if (f0n1 && f1n2 && !f0n3) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[3];
		   }

		   if ((f1n2 && f2n3 && !f0n1) ||
		       (f2n3 && f0n3 && !f1n2)) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[1];
		   }

		   if (f0n1 && f1n3 && !f2n3) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[2];
		   }

		   ligtyp[indx]->nfrag = 2;

		} else if ((f0n1 && f2n3 && !f1n2) || 
			   (f0n2 && f1n3 && !f0n1) || 
			   (f0n3 && f1n2 && !f0n1)) {
// two atoms are from one fragment, two others are from other frag:
// two fragments


		   if (f0n1 && f2n3 && !f1n2) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[2];
		   }
		   if (f0n2 && f1n3 && !f0n1) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[1];
		   }
		   if (f0n3 && f1n2 && !f0n1) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[1];
		   }

		   ligtyp[indx]->nfrag = 2;

		} else if ((f0n1 && !f0n2 && !f0n3) || 
			   (f0n2 && !f0n1 && !f0n3) || 
			   (f0n3 && !f0n1 && !f0n2) ||
			   (f1n2 && !f0n1 && !f1n3) ||
			   (f1n3 && !f0n1 && !f1n2) ||
			   (f2n3 && !f0n2 && !f1n2) ) {

// two atoms are from one fragment, two others are from different frags:
// three fragments
		   ligtyp[indx]->nfrag = 3;

		   if (f0n1 && !f0n2 && !f0n3) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[2];
			ligtyp[indx]->frag[2] = fragi[3];
		   }

		   if ((f0n2 && !f0n1 && !f0n3) ||
		       (f1n2 && !f0n1 && !f1n3)) {
			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[1];
			ligtyp[indx]->frag[2] = fragi[3];
		   }

		   if ((f0n3 && !f0n1 && !f0n2) ||
		       (f1n3 && !f0n1 && !f1n2) ||
		       (f2n3 && !f0n2 && !f1n2)) {

			ligtyp[indx]->frag[0] = fragi[0];
			ligtyp[indx]->frag[1] = fragi[1];
			ligtyp[indx]->frag[2] = fragi[2];
		   }

		} else {

// all four atoms are from different fragments

		   ligtyp[indx]->frag[0] = fragi[0];
		   ligtyp[indx]->frag[1] = fragi[1];
		   ligtyp[indx]->frag[2] = fragi[2];
		   ligtyp[indx]->frag[3] = fragi[3];
		   ligtyp[indx]->nfrag = 4;
		}
		break;
	default:
		break;
   }
}

int ceil_odd(arcl)
float arcl;
{
   int ires;

   ires = (int) ceil(arcl);
   if (ires % 2 != 1)  ires++;
   return ires;
 
}

 int equidist_npts(inttyp,b1,b2,b3,e1l)
 INCRSTRU *inttyp;
 double *b1;
 double *b2;
 double *b3;
 double e1l;
 {
   int ncirc[2],i,j,ntmp;
   float arcl[2], polrange,azirange;
   float a,D,D1,D2,theta,phi,thetad,phid,r,a1[2],a2[2],p1[2],p2[2],rq;
   int indx = 0, N,M1,M2,m,n;
   double x,y,z;

   if (inttyp->area.type == 3) {
	polrange = 180.0;
   } else {
	polrange = inttyp->area.polar2 - inttyp->area.polar1;
   }

   if (inttyp->area.type == 2 || inttyp->area.type == 3 || inttyp->area.type == 4) {
	azirange = 360.0;
   } else {
	azirange = inttyp->area.azimuth2 - inttyp->area.azimuth1;
   }

   arcl[0] = 1.0 + 2.0*PI*inttyp->area.rp * polrange / 
  	(360.0*inttyp->area.maxarc[0]);

   arcl[1] = 1.0 + 2.0*PI*inttyp->area.rp * azirange /
	(360.0*inttyp->area.maxarc[1]);

   ncirc[0] = ceil_odd(arcl[0]);
   ncirc[1] = ceil_odd(arcl[1]);

   polrange = polrange / (float) (ncirc[0] - 1);
   azirange = azirange / (float) (ncirc[1] - 1);

   a1[0] = inttyp->area.azimuth1;
   a1[1] = inttyp->area.azimuth2;

   if (inttyp->area.type == 1) {
	a2[0] = inttyp->area.azimuthb1;
	a2[1] = inttyp->area.azimuthb2;
   } else {
	a2[0] = 0.0;
	a2[1] = 180.0;
   }

   p1[0] = inttyp->area.polar1;
   p1[1] = inttyp->area.polar2;
   p2[0] = inttyp->area.polarb1;
   p2[1] = inttyp->area.polarb2;

   r = inttyp->area.rp;
   N = 4.0*PI*r*r/
	(inttyp->area.maxarc[0]*inttyp->area.maxarc[1]);
/*
   N = 4.0*PI*r*r/
	(inttyp->area.maxarc[0]*inttyp->area.maxarc[1]);
   N = 2000;
*/

   rq = r/inttyp->area.maxarc[0];
   N = 4.0*PI*rq*rq;
/*fprintf(stderr,"equi: N %d\n",N);*/
   N = 2000;
   r = r/toangs;
   a = 4.0*PI*r*r/N;
   D = sqrt(a);
   M1 = rndf(PI/D);
/*fprintf(stderr,"equi: D %f PI/D %f M1 %d\n",D,PI/D,M1);*/
   D1 = PI/ (float) M1;
   D2 = a / D1;
 
   indx = 0;

   if (inttyp->area.type == 2 || inttyp->area.type == 3 || 
		inttyp->area.type == 4) {

	if (inttyp->area.polar1 == 0.0) {
	   indx = 1;
	} else {
	   indx = 0;
	}

	ntmp = ncirc[0];
	if (inttyp->area.type == 3) ntmp = ncirc[0]-1;
	
	for (i = 1; i < ntmp; i++) {

	   theta = inttyp->area.polar1 + i*polrange;

 	   for (j = 0; j < ncirc[1]-1; j++) {
	      phi = inttyp->area.azimuth1 + j*azirange;

	      indx++; 
	   }
	}
	if (inttyp->area.type == 3) indx++;

   } else {

/*fprintf(stderr,"cal_area M1 %d \n",M1);*/
	for (m = 0; m < M1; m++) {

	   theta = PI * (((float) m) + 0.5) / ((float) M1);
	   thetad = theta*180.0/PI;
	   M2 = rndf(2.0*PI*sin(theta)/D2);

	   for (n = 0; n < M2; n++) {

		phi = 2.0*PI*((float) n) / ((float) M2);
		phid = phi*180.0/PI;
		if (phid > 270.0) phid = phid - 360.0;

		if ((phid >= p1[0] && phid <= p1[1]) ||
		    (phid >= p2[0] && phid <= p2[1]) ) {
		if ((thetad >= a1[0] && thetad <= a1[1])  || 
		    (thetad >= a2[0] && thetad <= a2[1]) ) {

	   	indx++;

		} /* if end */

		
	   } /* if end */
	} /* for n end */
     } /* for m end */
   }

   return indx;
 }

 void equidist_sphere(inttyp,b1,b2,b3,ori)
 INCRSTRU *inttyp;
 double *b1;
 double *b2;
 double *b3;
 double *ori;
 {
   int ncirc[2],i,j,ntmp;
   float arcl[2], polrange,azirange;
   float a,D,D1,D2,theta,phi,thetad,phid,r,a1[2],a2[2],p1[2],p2[2],rq;
   int indx = 0, N,M1,M2,m,n;
   double x,y,z;

   if (inttyp->area.type == 3) {
	polrange = 180.0;
   } else {
	polrange = inttyp->area.polar2 - inttyp->area.polar1;
   }

   if (inttyp->area.type == 2 || inttyp->area.type == 3 || 
	inttyp->area.type == 4) {
	azirange = 360.0;
   } else {
	azirange = inttyp->area.azimuth2 - inttyp->area.azimuth1;
   }

   arcl[0] = 1.0 + PI*inttyp->area.rp * polrange / 
  	(180.0*inttyp->area.maxarc[0]);

   arcl[1] = 1.0 + PI*inttyp->area.rp * azirange /
	(180.0*inttyp->area.maxarc[1]);

   ncirc[0] = ceil_odd(arcl[0]);
   ncirc[1] = ceil_odd(arcl[1]);

   polrange = polrange / (float) (ncirc[0] - 1);
   azirange = azirange / (float) (ncirc[1] - 1);


   r = inttyp->area.rp;
/*
   N = 4.0*PI*r*r/
	(inttyp->area.maxarc[0]*inttyp->area.maxarc[1]);
   N = 2000;
*/

   a1[0] = inttyp->area.azimuth1;
   a1[1] = inttyp->area.azimuth2;

   if (inttyp->area.type == 1) {
	a2[0] = inttyp->area.azimuthb1;
	a2[1] = inttyp->area.azimuthb2;
   } else {
	a2[0] = 0.0;
	a2[1] = 180.0;
   }

   p1[0] = inttyp->area.polar1;
   p1[1] = inttyp->area.polar2;
   p2[0] = inttyp->area.polarb1;
   p2[1] = inttyp->area.polarb2;


   rq = r/inttyp->area.maxarc[0];
   N = 4.0*PI*rq*rq;
   r = r/toangs;
   N = 2000;
   a = 4.0*PI*r*r/N;
   D = sqrt(a);
   M1 = rndf(PI/D);
   D1 = PI/ (float) M1;
   D2 = a / D1;
 
   indx = 0;

   if (inttyp->area.type == 2 || inttyp->area.type == 3 || inttyp->area.type == 4) {

	x = 0.0;
	y = 0.0;
	z = r;

	if (inttyp->area.polar1 == 0.0) {

	   inttyp->points[0] = ori[0] + x*b3[0] + y*b2[0] + z*b1[0];
	   inttyp->points[1] = ori[1] + x*b3[1] + y*b2[1] + z*b1[1];
	   inttyp->points[2] = ori[2] + x*b3[2] + y*b2[2] + z*b1[2];

	   indx = 1;
	} else {
	   indx = 0;
	}

	ntmp = ncirc[0];
	if (inttyp->area.type == 3) ntmp = ncirc[0]-1;
	
	for (i = 1; i < ntmp; i++) {

//	   theta = ((double) i)*polrange;
	   theta = (double) inttyp->area.polar1 + ((double) i)*polrange;
	   theta = PI*theta / 180.0;


 	   for (j = 0; j < ncirc[1]-1; j++) {

	      phi = ((double) j)*azirange;
	      phi = PI*phi / 180.0;

	      x = r*sin(theta)*cos(phi);
	      y = r*sin(theta)*sin(phi);
	      z = r*cos(theta);

	      inttyp->points[indx*3+0] = ori[0] + x*b3[0] + y*b2[0] + z*b1[0];
	      inttyp->points[indx*3+1] = ori[1] + x*b3[1] + y*b2[1] + z*b1[1];
	      inttyp->points[indx*3+2] = ori[2] + x*b3[2] + y*b2[2] + z*b1[2];
	      indx++; 
	   }
	}

	if (inttyp->area.type == 3) {

	   x = 0.0;
	   y = 0.0;
	   z = -r;

	   inttyp->points[indx*3+0] = ori[0] + x*b3[0] + y*b2[0] + z*b1[0];
	   inttyp->points[indx*3+1] = ori[1] + x*b3[1] + y*b2[1] + z*b1[1];
	   inttyp->points[indx*3+2] = ori[2] + x*b3[2] + y*b2[2] + z*b1[2];

	   indx++;
	}

   } else {

	for (m = 0; m < M1; m++) {
	   theta = PI * (((float) m) + 0.5) / ((float) M1);
	   thetad = theta*180.0/PI;
	   M2 = rndf(2.0*PI*sin(theta)/D2);
	   for (n = 0; n < M2; n++) {
		phi = 2.0*PI*((float) n) / ((float) M2);
		phid = phi*180.0/PI;
		if (phid > 270.0) phid = phid - 360.0;

		if ((phid >= p1[0] && phid <= p1[1]) ||
		    (phid >= p2[0] && phid <= p2[1]) ) {
		  if ((thetad >= a1[0] && thetad <= a1[1])  || 
		       (thetad >= a2[0] && thetad <= a2[1]) ) {

		   x = r*sin(theta)*cos(phi);
		   y = r*sin(theta)*sin(phi);
	 	   z = r*cos(theta);

		   inttyp->points[indx*3+0] = 
			inttyp->c[0][0] + x*b2[0] + y*b3[0] + z*b1[0];
	   	   inttyp->points[indx*3+1] = 
			inttyp->c[0][1] + x*b2[1] + y*b3[1] + z*b1[1];
	   	   inttyp->points[indx*3+2] = 
			inttyp->c[0][2] + x*b2[2] + y*b3[2] + z*b1[2];

	   	   indx++;

		  } /* if end */

		
	        } /* if end */
	   } /* for n end */
	} /* for m end */
   }

 }

 void cal_area(inttyp)
 INCRSTRU *inttyp;
 {
 int ncirc[2],i,j,indx,bole;
 float arcl[2], polrange,azirange,phi,theta;
 double e0[3],e1[3],e2[3],e3[3],ori[3];
 double b1[3],b2[3],b3[3];
 double x,y,z,e1l,e2l,e1lt,e2lt;

 e1[0] = 0.0; e1[1] = 0.0; e1[2] = 1.0;
 e2[0] = 1.0; e2[1] = 0.0; e2[2] = 0.0;
 e3[0] = 0.0; e3[1] = 1.0; e3[2] = 0.0;

 for (i = 0; i < 3; i++) {
    if (inttyp->area.type != 3) {
	e1[i] =  inttyp->c[1][i] - inttyp->c[0][i];
	if (inttyp->area.type != 2 && inttyp->area.type != 3) {
	   e2[i] =  inttyp->c[2][i] - inttyp->c[0][i];
	}
	if (inttyp->area.type == 6) {
	   e3[i] =  inttyp->c[3][i] - inttyp->c[0][i];
	}
    }
 }

 for (i = 0; i < 3; i++) {
	ori[i] = inttyp->c[0][i] + 
		inttyp->area.center[0]*e1[i] + 
		inttyp->area.center[1]*e2[i] +
		inttyp->area.center[2]*e3[i];
	inttyp->ORI[i] = ori[i];
 }


/*
transform to orthogonal basis:
FIRST normalize e1,e2,e3
*/

 e1l = dveclen(e1);
 e2l = dveclen(e2);

 if (inttyp->area.type != 6) {
    for (i = 0; i < 3; i++) {
	e1[i] = e1[i] / e1l;
	e2[i] = e2[i] / e2l;
    }
    crossprd(e1,e2,e3);
 }

 for (i = 0; i < 3; i++) {
	b1[i] = e1[i];
	b2[i] = e2[i];
	b3[i] = e3[i];
 }

 for (i = 0; i < 3; i++) {
    if (inttyp->area.type != 3) {
	e1[i] = inttyp->area.v1[0]*b1[i] + inttyp->area.v1[1]*b2[i] +
		inttyp->area.v1[2]*b3[i];
	if (inttyp->area.type != 2 && inttyp->area.type != 3 && 
		inttyp->area.type != 4 && inttyp->area.type != 5 &&
		inttyp->area.type != 6) {
	   e2[i] = inttyp->area.v2[0]*b1[i] + inttyp->area.v2[1]*b2[i] +
		inttyp->area.v2[2]*b3[i];
	}
    }
 }

 e1lt = dveclen(e1);
 e2lt = dveclen(e2);

 for (i = 0; i < 3; i++) {
	e1[i] = e1[i] / e1lt;
	e2[i] = e2[i] / e2lt;
	b1[i] = e1[i];
 }

 crossprd(e1,e2,e3);

 if (inttyp->area.type == 5 || inttyp->area.type == 6) {
    crossprd(e1,e3,e2);
    for (i = 0; i < 3; i++) {
	b1[i] = e1[i];
	b2[i] = e2[i];
	b3[i] = e3[i];
    }
    inttyp->area.type = 2;

 } else {
    crossprd(e1,e3,b2);
    crossprd(b1,b2,b3);
 }

 inttyp->npts = equidist_npts(inttyp,b1,b2,b3,e1l);

 if (inttyp->npts != 0) {

    inttyp->points =  (double *) malloc((sizeof x)*(inttyp->npts+1)*3);

    equidist_sphere(inttyp,b1,b2,b3,ori);
 }

}

#define N_GROUPS      7
#define H_ACC_GROUP   0
#define H_DON_GROUP   1
#define PHC_GROUP     2
#define PHR_GROUP     3
#define ARO_GROUP     4
#define MET_GROUP     5
#define MACC_GROUP    6

static double dckcoff = DCKCOFF;
static int FiltAD =  0;
static int prE =  0;
static int hpr =  1;
static int DistI[N_GROUPS];
static int PDist[N_GROUPS];
static int NDist[N_GROUPS];
static int *IDist[N_GROUPS];
static GRPSTRU XGRP[N_GROUPS][N_GROUPS];

int Wrt_table(char *outf)
{
   FILE *outfile;
   int l,k,ret;

   outfile = fopen(outf, "w");
   ret = 0;

   for (l=0; l < N_GROUPS; l++) {
	for (k=l; k < N_GROUPS; k++) {
		fwrite(&XGRP[l][k],sizeof(GRPSTRU),1,outfile);
	}
   }
   
   for (l=0; l < ACTIVE_GROUPS; l++) {
	for (k=l; k < ACTIVE_GROUPS; k++) {
	   fwrite(XGRP[l][k].XDist,sizeof(CROSSSTRU), 
		XGRP[l][k].n, outfile);
	   fwrite(XGRP[l][k].XHash,sizeof(HASHSTRU), 
		XGRP[l][k].l+1, outfile);
	}
   }
   
   if (fwrite != 0) {
	printf("contents to file %s written successfully !\n",outf);
	ret = 1;
   } else {
	printf("error writing file %s !\n",outf);
   }

   fclose(outfile);

   return(ret);
}

void RD_table(char *outf)
{
   FILE *infile;
   int l,k;

   infile = fopen(outf, "r");

   for (l=0; l < N_GROUPS; l++) {
	for (k=l; k < N_GROUPS; k++) {
		fread(&XGRP[l][k],sizeof(GRPSTRU),1,infile);
   		XGRP[l][k].XDist = 
			(CROSSSTRU *) malloc(sizeof(CROSSSTRU)*XGRP[l][k].n);
		XGRP[l][k].XHash =
			(HASHSTRU *) malloc(sizeof(HASHSTRU)*(XGRP[l][k].l+1));
	}
   }
   
   for (l=0; l < ACTIVE_GROUPS; l++) {
	for (k=l; k < ACTIVE_GROUPS; k++) {
	   fread(XGRP[l][k].XDist,sizeof(CROSSSTRU), 
		XGRP[l][k].n, infile);
	   fread(XGRP[l][k].XHash,sizeof(HASHSTRU), 
		XGRP[l][k].l+1, infile);
	}
   }
   
   fclose(infile);

   return;
}

int cmpcrs(a,b)
CROSSSTRU *a, *b;
{
    if (a->d > b->d) return 1;
    else
       if (a->d == b->d) return  0;
       else          return -1;
}

int CmpORI(ORI1,ORI2)
double *ORI1;
double *ORI2;
{
    int i,j;

    for (i=0; i < 3; i++)  if (ORI1[i] != ORI2[i]) return 1;
   
    return 0;
}

int GetCrossGroup(grp1,grp2,fill)
int grp1;
int grp2;
int fill;
{
    int i,j,k,l,m,n,id1,id2;
    double dd,tt;
    
    n = 0;

    for (i=0; i < DistI[grp1]; i++) {
	id1 = IDist[grp1][i];
	for (k=0; k < inttyp[id1]->npts; k++) {
	   for (j=i+1; j < DistI[grp2]; j++) {
	     id2 = IDist[grp2][j];
	     if (CmpORI(inttyp[id1]->ORI, inttyp[id2]->ORI)) {
		for (l=0; l < inttyp[IDist[grp2][j]]->npts; l++) {
		   dd = 0.0;
		   for (m=0; m < 3; m++) {
		   	tt = inttyp[id1]->points[k*3+m] -
			     inttyp[id2]->points[l*3+m];
			dd = dd + tt*tt;

		   }
		   dd = sqrt(dd)*toangs;
		   if (dd < dckcoff && dd > DCKCMIN) {
			if (! ((id1 == id2) && (k == l))) {

			 if (fill) {
			   XGRP[grp1][grp2].XDist[n].d = (float) dd;
			   XGRP[grp1][grp2].XDist[n].grp1 = grp1;
			   XGRP[grp1][grp2].XDist[n].ind1 = IDist[grp1][i];
			   XGRP[grp1][grp2].XDist[n].pnt1 = k;
			   XGRP[grp1][grp2].XDist[n].grp2 = grp2;
			   XGRP[grp1][grp2].XDist[n].ind2 = IDist[grp2][j];
			   XGRP[grp1][grp2].XDist[n].pnt2 = l;
			 }
			 n++;
			}
		   }
		}
	      }
	   }
	}
    }

    return n;
}

int CrossGrpDist1(ogrp1,ogrp2,d,arr1,narr1,arr2,narr2,Tri)
int ogrp1;
int ogrp2;
float d;
int *arr1;
int narr1;
int *arr2;
int narr2;
TRISTRU *Tri;
{
   int i,j,k,idmin,idmax,d100,n;
   float dd,dmin,dmax;
   GRPSTRU *grp_p01;
   CROSSSTRU *xrsii;

// we need a way to esthablish a link of the kind of group
// with the kind of array: there should be a link between
// the type of the group and which array, eg; idon vs iaro
    
   d100 = (int) dckcoff*dckcoff;

   dmin = ABS(d - DCKdev); 
   if (dmin > (float) dckcoff) {
	idmin = d100;
   } else if (dmin < DCKCMIN) {
	idmin = 1;
   } else {
	idmin = (int) rndf(dmin*10.0);
	if (idmin > d100) return(0);
   }

   dmax = ABS(d + DCKdev); 
   if (dmax > (float) dckcoff) {
	idmax = d100;
   } else if (dmax < DCKCMIN) {
	idmax = 1;
   } else {
	idmax = (int) rndf(dmax*10.0);
	if (idmax > d100) idmax = d100;
   }

   for (i=0; i < XGRP[ogrp1][ogrp2].n; i++) {
     for (j=0; j < narr1; j++) {
       for (k=0; k < narr2; k++) {
	  if (XGRP[ogrp1][ogrp2].XDist[i].ind1 == arr1[j] &&
	    XGRP[ogrp1][ogrp2].XDist[i].ind2 == arr2[k]) {
	     if (ABS(XGRP[ogrp1][ogrp2].XDist[i].d-d) < DCKdev) {
		return(1);
	     }
	  }
       }
     }
   }

   return(0);
}

void ScanCrossGroup(grp1,grp2,ind1,ind2)
int grp1;
int grp2;
int ind1;
int ind2;
{
    int i;
    
    fprintf(stderr,"ScanCrossGroup: [%d,%d] for distances between interactionpoints %d %d\n\n",grp1,grp2,ind1,ind2);
    for (i=0; i < XGRP[grp1][grp2].n; i++) {
	if (XGRP[grp1][grp2].XDist[i].ind1 == ind1 &&
	    XGRP[grp1][grp2].XDist[i].ind2 == ind2) {
fprintf(stderr,"d %.3f pnt1 %d pnt2 %d\n",XGRP[grp1][grp2].XDist[i].d,XGRP[grp1][grp2].XDist[i].pnt1,XGRP[grp1][grp2].XDist[i].pnt2);
	}

    }

}

void ScanCrossGroupDist(grp1,grp2,ind1,ind2,d)
int grp1;
int grp2;
int ind1;
int ind2;
float d;
{
   int i,ii,iii,j,idmin,idmax,d100,n;
   float dd,dmin,dmax;
   GRPSTRU *grp_p01;
   CROSSSTRU *xrsii;
    
   d100 = (int) dckcoff*dckcoff;

   dmin = ABS(d - DCKdev); 
   if (dmin > (float) dckcoff) {
	idmin = d100;
   } else if (dmin < DCKCMIN) {
	idmin = 1;
   } else {
	idmin = (int) rndf(dmin*10.0);
	if (idmin > d100) return;
   }

   dmax = ABS(d + DCKdev); 
   if (dmax > (float) dckcoff) {
	idmax = d100;
   } else if (dmax < DCKCMIN) {
	idmax = 1;
   } else {
	idmax = (int) rndf(dmax*10.0);
	if (idmax > d100) idmax = d100;
   }

   fprintf(stderr,"ScanCrossGroupD: [%d,%d] for distances %.3f between interactionpoints %d %d\n\n",grp1,grp2,d,ind1,ind2);
   for (i=0; i < XGRP[grp1][grp2].n; i++) {
	if (XGRP[grp1][grp2].XDist[i].ind1 == ind1 &&
	    XGRP[grp1][grp2].XDist[i].ind2 == ind2) {
	   if (ABS(XGRP[grp1][grp2].XDist[i].d-d) < DCKdev) {
fprintf(stderr,"d %.3f pnt1 %d pnt2 %d\n",XGRP[grp1][grp2].XDist[i].d,XGRP[grp1][grp2].XDist[i].pnt1,XGRP[grp1][grp2].XDist[i].pnt2);
	   }
	}

   }

   fprintf(stderr,"ScanCrossGroupD: [%d,%d] for distances %.3f via XHash of interaction points %d %d\n\n",grp1,grp2,d,ind1,ind2);
   fprintf(stderr,"ScanCrossGroupD: [%d,%d] for distances %.3f via XHash idmin %d idmax %d\n\n",grp1,grp2,d,idmin,idmax);
   grp_p01 = &XGRP[grp1][grp2];

   for (i = idmin; i < idmax+1; i++ ) {
	n   = grp_p01->XHash[i].n;
	ii  = grp_p01->XHash[i].ind;

	if (ii+n >= grp_p01->n) break;

	for (j = 0; j < n; j++ ) {

	   iii = ii + j;
	   xrsii = &grp_p01->XDist[iii];

	   if (i == idmin && j == 0) fprintf(stderr,"dist[%d,%d] %.3f \n",iii,ii,xrsii->d);
	   if (ABS(xrsii->d-d) < DCKdev && xrsii->ind1 == ind1 && xrsii->ind2 == ind2) {
		fprintf(stderr,"d %.3f pnt1 %d pnt2 %d iii %d\n",
			xrsii->d,xrsii->pnt1,xrsii->pnt2,iii);
	   }
	}
   }
}

void PrtInt(int i1,int i2,int i3,int j1,int j2,int j3)
{
    int i,j,k,m;
    double dd,tt;
    double d12,d13,d23;
    double d12min,d13min,d23min;
    double d12max,d13max,d23max;
    double D12,D13,D23;
    double v1[3],v2[3],v3[3];

// This function test for the existance of a triplet (i1,i2,i3)
// of protein interaction points, against a ligand triplet (j1,j2,j3)
// THIS IS ACCOMPLISHED without the setup_distances tables !!

// First create distances from ligand interaction points

    if (j1 >= lintp || j2 >= lintp || j3 >= lintp) return;

    for (i = 0; i<3; i++ ) {
      v1[i] = ligtyp[j1]->ORI[i] - ligtyp[j2]->ORI[i];
      v2[i] = ligtyp[j2]->ORI[i] - ligtyp[j3]->ORI[i];
      v3[i] = ligtyp[j1]->ORI[i] - ligtyp[j3]->ORI[i];
    }
    D12 = dveclen(v1)*toangs;
    D23 = dveclen(v2)*toangs;
    D13 = dveclen(v3)*toangs;

    d12min = BIGD; d13min = BIGD; d23min = BIGD;
    d12max = 0.0; d13max = 0.0; d23max = 0.0;

    if (i1 >= nintp || i2 >= nintp || i3 >= nintp) return;

    for (i=0; i<inttyp[i1]->npts; i++) {
       for (j=0; j<inttyp[i2]->npts; j++) {

	  d12 = 0.0;
	  for (m=0; m < 3; m++) {
	  	tt = inttyp[i1]->points[i*3+m] -
		     inttyp[i2]->points[j*3+m];
		d12 = d12 + tt*tt;
	  }
	  d12 = sqrt(d12)*toangs;
	  if (d12 < d12min) d12min = d12;
	  if (d12 > d12max) d12max = d12;

          for (k=0; k<inttyp[i3]->npts; k++) {
		d13 = 0.0;
		for (m=0; m < 3; m++) {
		   	tt = inttyp[i1]->points[i*3+m] -
			     inttyp[i3]->points[k*3+m];
			d13 = d13 + tt*tt;
		}
		d13 = sqrt(d13)*toangs;
		if (d13 < d13min) d13min = d13;
		if (d13 > d13max) d13max = d13;

		d23 = 0.0;
		for (m=0; m < 3; m++) {
		   	tt = inttyp[i2]->points[j*3+m] -
			     inttyp[i3]->points[k*3+m];
			d23 = d23 + tt*tt;

		}
		d23 = sqrt(d23)*toangs;
		if (d23 < d23min) d23min = d23;
		if (d23 > d23max) d23max = d23;

	  }
       }
    }
}

void Setup_Distance_Tables()
{
    int i,j,k,l,m,n,jnew,ll,kk;
    double dd,tt;
    double d12,d13,d23;
    int done;

fprintf(stderr,"Setup_Distance_Tables\n");

    for (i=0; i<N_GROUPS; i++) {
	PDist[i] = 0;
	NDist[i] = 0;
	DistI[i] = 0;
    }

    for (i=0; i<nintp; i++) {
	switch (inttyp[i]->type) {
	case H_ACC:
		PDist[H_ACC_GROUP] = PDist[H_ACC_GROUP] + inttyp[i]->npts;
		NDist[H_ACC_GROUP]++;
		break;

	case H_DON:
		PDist[H_DON_GROUP] = PDist[H_DON_GROUP] + inttyp[i]->npts;
		NDist[H_DON_GROUP]++;
		break;
		
	case PHENYL_CENTER:
		PDist[PHC_GROUP] = PDist[PHC_GROUP] + inttyp[i]->npts;
		NDist[PHC_GROUP]++;
		if (inttyp[i]->type == PHENYL_CENTER) {
		   PDist[PHR_GROUP] = PDist[PHR_GROUP] + inttyp[i]->npts;
		   NDist[PHR_GROUP]++;
		}
		break;
		
	case AMIDE:
	case PHE_CH3:
	case PHENYL_RING:
		PDist[PHR_GROUP] = PDist[PHR_GROUP] + inttyp[i]->npts;
		NDist[PHR_GROUP]++;
		if (inttyp[i]->type == PHENYL_RING) {
		   PDist[PHC_GROUP] = PDist[PHC_GROUP] + inttyp[i]->npts;
		   NDist[PHC_GROUP]++;
		}
		break;
		
	case CH:
	case CH2:
	case CH3:
	case SULFUR:
	case ARO:
		PDist[ARO_GROUP] = PDist[ARO_GROUP] + inttyp[i]->npts;
		NDist[ARO_GROUP]++;
		break;
		
	case METAL:
		PDist[MET_GROUP] = PDist[MET_GROUP] + inttyp[i]->npts;
		NDist[MET_GROUP]++;
		break;

	case METAL_ACC:
		PDist[MACC_GROUP] = PDist[MACC_GROUP] + inttyp[i]->npts;
		NDist[MACC_GROUP]++;
		break;
	}
    }

    for (i=0; i<N_GROUPS; i++) {
	IDist[i] = (int *) malloc(sizeof(int)*NDist[i]);
    }

    for (i=0; i<nintp; i++) {
	switch (inttyp[i]->type) {
	case H_ACC:
		IDist[H_ACC_GROUP][DistI[H_ACC_GROUP]] = i;
		DistI[H_ACC_GROUP]++;
		break;

	case H_DON:
		IDist[H_DON_GROUP][DistI[H_DON_GROUP]] = i;
		DistI[H_DON_GROUP]++;
		break;
		
	case PHENYL_CENTER:
		IDist[PHC_GROUP][DistI[PHC_GROUP]] = i;
		DistI[PHC_GROUP]++;
		if (inttyp[i]->type == PHENYL_CENTER) {
		   IDist[PHR_GROUP][DistI[PHR_GROUP]] = i;
		   DistI[PHR_GROUP]++;
		}
		break;
		
	case AMIDE:
	case PHE_CH3:
	case PHENYL_RING:
		IDist[PHR_GROUP][DistI[PHR_GROUP]] = i;
		DistI[PHR_GROUP]++;
		if (inttyp[i]->type == PHENYL_RING) {
		   IDist[PHC_GROUP][DistI[PHC_GROUP]] = i;
		   DistI[PHC_GROUP]++;
		}
		break;
		
	case CH:
	case CH2:
	case CH3:
	case SULFUR:
	case ARO:
		IDist[ARO_GROUP][DistI[ARO_GROUP]] = i;
		DistI[ARO_GROUP]++;
		break;
		
	case METAL:
		IDist[MET_GROUP][DistI[MET_GROUP]] = i;
		DistI[MET_GROUP]++;
		break;

	case METAL_ACC:
		IDist[MACC_GROUP][DistI[MACC_GROUP]] = i;
		DistI[MACC_GROUP]++;
		break;
	}
    }

    for (l=0; l < N_GROUPS; l++) {
	for (k=l; k < N_GROUPS; k++) {
	   if (l < ACTIVE_GROUPS && k < ACTIVE_GROUPS) {
	      XGRP[l][k].n = GetCrossGroup(l,k,0);

	      XGRP[l][k].XDist = NULL;
	      XGRP[l][k].XHash = NULL;

	      if (XGRP[l][k].n != 0) {
		XGRP[l][k].XDist = 
			(CROSSSTRU *) malloc(sizeof(CROSSSTRU)*XGRP[l][k].n);

		if (XGRP[l][k].XDist == NULL) 
			fprintf(stderr,"Failed to allocate memory !\n");

		XGRP[l][k].n = GetCrossGroup(l,k,1);

		qsort((CROSSSTRU *) XGRP[l][k].XDist, 
		    XGRP[l][k].n, sizeof(CROSSSTRU), cmpcrs);

		XGRP[l][k].l = 
			(int) rndf(XGRP[l][k].XDist[XGRP[l][k].n-1].d*10.0);

		XGRP[l][k].XHash = 
			(HASHSTRU *) malloc(sizeof(HASHSTRU)*(XGRP[l][k].l+1));
    
		for (i=0; i<XGRP[l][k].l; i++) {
		    XGRP[l][k].XHash[i].n = 0;
		    XGRP[l][k].XHash[i].ind = 0;
		}

		jnew = -1;
		ll = 0;

		for (i=0; i<XGRP[l][k].n; i++) {
		   j = (int) rndf(XGRP[l][k].XDist[i].d*10.0);
		   if (j != jnew) {
			if (jnew != -1) XGRP[l][k].XHash[jnew].n = ll;
			XGRP[l][k].XHash[j].ind = i;
			ll = 0;
			jnew = j;
	   	   }
	   	   ll++;
		}

	      }
	   } else {
	      XGRP[l][k].n = 0;

	      XGRP[l][k].XDist = NULL;
	      XGRP[l][k].XHash = NULL;
	   }
	}
    }

// lig 62 Donor, prot 68 acceptor: H_ACC = 0
// lig 64 Donor, prot 76 acceptor: H_ACC = 0
// lig 63 Donor, prot 67 acceptor: H_ACC = 0

//    ScanCrossGroup(0,0,68,76);
//    ScanCrossGroup(0,0,67,68);
//    ScanCrossGroup(0,0,67,76);

//    ScanCrossGroupDist(0,0,2,17,11.949);
//    ScanCrossGroupDist(0,4,2,1,3.618);
//    ScanCrossGroupDist(0,4,2,0,2.395);
//    ScanCrossGroupDist(0,0,68,76,3.660);
//    ScanCrossGroupDist(0,0,67,68,2.334);
//    ScanCrossGroupDist(0,0,67,76,1.837);
//    PrtInt(151,150,160,23,14,11);
}

int Find_Group(grp)
int grp;
{
   switch (grp) {
   case H_ACC:
	return H_ACC_GROUP;
	break;

   case H_DON:
	return H_DON_GROUP;
	break;
		
   case PHENYL_CENTER:
	return PHC_GROUP;
	break;
		
   case AMIDE:
   case PHE_CH3:
   case PHENYL_RING:
	return PHR_GROUP;
	break;
		
   case CH:
   case CH2:
   case CH3:
   case SULFUR:
   case ARO:
	return ARO_GROUP;
	break;
		
   case METAL:
	return MET_GROUP;
	break;

   case METAL_ACC:
	return MACC_GROUP;
	break;
   }
}

int Find_Matching_Group(grp)
int grp;
{
   switch (grp) {
   case H_ACC_GROUP:
	return H_DON_GROUP;
	break;
   case H_DON_GROUP:
	return H_ACC_GROUP;
	break;
   case PHC_GROUP:
	return PHR_GROUP;
	break;
   case PHR_GROUP:
	return PHC_GROUP;
	break;
   case ARO_GROUP:
	return ARO_GROUP;
	break;
   case MET_GROUP:
	return MACC_GROUP;
	break;
   case MACC_GROUP:
	return MET_GROUP;
	break;
   }
}

void Calc_Outvector(TRISTRU *Tri)
{
   int i;
   float v1[3],v2[3],v3[3],dd;

   for (i = 0; i<3; i++ ) {
      v1[i] = Tri->p2c[i] - Tri->p1c[i];
      v2[i] = Tri->p3c[i] - Tri->p1c[i];
      v3[i] = Tri->p3c[i] - Tri->p2c[i];
   }
   cross(v1,v2,Tri->Out);

   dd = veclen(Tri->Out);

   if (dd > 0.0) {
      for (i = 0; i<3; i++ ) Tri->Out[i] = Tri->Out[i] / dd;
   }
}

void Calc_Centroid(TRISTRU *Tri)
{

/* calculates centroid of a triangle */
/* should also fill in l,k,m */

   int i,j,k,l;
   float v1[3],v2[3],v3[3],dd;
   
   for (i = 0; i<3; i++ ) {
      Tri->Cen[i] = (Tri->p1[i] + Tri->p2[i] + Tri->p3[i]) / 3.0;
      v1[i] = Tri->p2[i] - Tri->p1[i];
      v2[i] = Tri->p3[i] - Tri->p1[i];
      v3[i] = Tri->p3[i] - Tri->p2[i];
   }
   Tri->d12 = veclen(v1)*toangs;
   Tri->d13 = veclen(v2)*toangs;
   Tri->d23 = veclen(v3)*toangs;

   cross(v1,v2,Tri->Out);
   dd = veclen(Tri->Out);
   if (dd > 0.0) {
      for (i = 0; i<3; i++ ) Tri->Out[i] = Tri->Out[i] / dd;
   }

/* to tranform one triangle onto another:
   1 Translate Tri1.Cen[] to Tri2.Cen[]
   2 Take the two outvectors Tri1.Out[] and Tri2.Out[],
     calculate out vector from these vecs. This will be the axis of
     rotation,
     Take outvector of Out(Rot) x Tri2.out = OutF
     Now Out(Rot),Tri2.out and OutF form the basis on which will be rotatied
         z       ,x            y
   3 Now rotate Tri1 around Tri2.out, such that Tri1.p1[] == Tri2.p1[]
*/
}

static int itry = 1;

typedef struct { float X; float Y; float Z; } TXYZ;

float Magnitude( TXYZ *Point1, TXYZ *Point2 )
{
    TXYZ Vector;

    Vector.X = Point2->X - Point1->X;
    Vector.Y = Point2->Y - Point1->Y;
    Vector.Z = Point2->Z - Point1->Z;

    return (float) sqrt(Vector.X*Vector.X + Vector.Y*Vector.Y + Vector.Z*Vector.Z );
}

int DPointLine(TXYZ *Point,TXYZ *LineStart,TXYZ *LineEnd,float *Distance)
{
    float LineMag;
    float U;
    TXYZ Intersection;
 
    LineMag = Magnitude( LineEnd, LineStart );
 
    U = ( ( ( Point->X - LineStart->X ) * ( LineEnd->X - LineStart->X ) ) +
        ( ( Point->Y - LineStart->Y ) * ( LineEnd->Y - LineStart->Y ) ) +
        ( ( Point->Z - LineStart->Z ) * ( LineEnd->Z - LineStart->Z ) ) ) /
        ( LineMag * LineMag );
 
    if( U < 0.0f || U > 1.0f )
        return 0;   // closest point does not fall within the line segment
 
    Intersection.X = LineStart->X + U * ( LineEnd->X - LineStart->X );
    Intersection.Y = LineStart->Y + U * ( LineEnd->Y - LineStart->Y );
    Intersection.Z = LineStart->Z + U * ( LineEnd->Z - LineStart->Z );
 
    *Distance = Magnitude( Point, &Intersection );
 
    return 1;
}

float Check_TriS(TRISSTRU *Tri)
{


   int i;
   float v1[3],v2[3],v3[3],cosa;
   
   for (i = 0; i<3; i++ ) {
      v1[i] = Tri->p2[i] - Tri->p1[i];
      v2[i] = Tri->p3[i] - Tri->p1[i];
      v3[i] = Tri->p3[i] - Tri->p2[i];
   }

   IMPRD(v1,v2,&cosa,1);

   return(cosa);
}

float Check_Tri(TRISTRU *Tri)
{


   int i;
   float v1[3],v2[3],v3[3],cosa;
   
   for (i = 0; i<3; i++ ) {
      v1[i] = Tri->p2[i] - Tri->p1[i];
      v2[i] = Tri->p3[i] - Tri->p1[i];
      v3[i] = Tri->p3[i] - Tri->p2[i];
   }

   IMPRD(v1,v2,&cosa,1);

   return(cosa);
}

void R3calc(Tri1,Tri2,Tri1AD0,Tri2AD0)
TRISTRU *Tri1;
TRISTRU *Tri2;
float *Tri1AD0;
float *Tri2AD0;
{
   int i,j;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float cosa,sina;
   double R3[4][4];

// Tri1 DOES NOT CHANGE

// Is this the correct way to calculate Tri2 outvector ??

   Calc_Outvector(Tri2);

   for (j=0; j < 3; j++) {
	v1[j] = Tri2->Out[j];
	v2[j] = Tri2->Cen[j] - Tri2->p1c[j];
	V1[j] = Tri1->Out[j];
   }

   vecnrm(v1);
   vecnrm(v2);

   for (j=0; j < 3; j++) {
	Tri2->v[j] = v2[j];
   }

   cross(v1,v2,v3);
   
   vecnrm(v3);

// v1 is new outvector of Tri2, it should however still be
// rotated to match Tri1->Out position

   IMPRD(v1,V1,&cosa,1);
   IMPRD(v3,V1,&sina,1);

// rotate around v2, v2 = vector 

   Frst_Rot(Tri2->Cen,v2,sina,cosa,R3);

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri2->R3[i][j] = R3[i][j];
}

void Frst_Rot(cc,uu,sina,cosa,R)
float *cc;
float *uu;
double sina;
double cosa;
double R[4][4];
{
// rotate around an arbitary vector in space (uu) from the center (cc)
// angle to rotate around defined by sina and cosa
// the uu vector NEEDS to be normalized !!!

    int i,j;
    double ca,sa,c[3],u[3];

    ca = cosa;
    sa = sina;

    for (i = 0; i<3; i++ ) {
	c[i] = (double) cc[i];
	u[i] = (double) uu[i];
    }

    R[0][0] = u[0]*u[0] + (u[1]*u[1] + u[2]*u[2])*ca;
    R[0][1] = u[0]*u[1]*(1.0 - ca) - u[2]*sa;
    R[0][2] = u[0]*u[2]*(1.0 - ca) + u[1]*sa;
    R[0][3] = (c[0]*(u[1]*u[1]+u[2]*u[2])-u[0]*(c[1]*u[1]+c[2]*u[2]))*(1.0 - ca) + (c[1]*u[2] - c[2]*u[1])*sa;

    R[1][0] = u[0]*u[1]*(1.0 - ca) + u[2]*sa;
    R[1][1] = u[1]*u[1] + (u[0]*u[0] + u[2]*u[2])*ca;
    R[1][2] = u[1]*u[2]*(1.0 - ca) - u[0]*sa;
    R[1][3] = (c[1]*(u[0]*u[0]+u[2]*u[2])-u[1]*(c[0]*u[0]+c[2]*u[2]))*(1.0 - ca) + (c[2]*u[0] - c[0]*u[2])*sa;

    R[2][0] = u[0]*u[2]*(1.0 - ca) - u[1]*sa;
    R[2][1] = u[1]*u[2]*(1.0 - ca) + u[0]*sa;
    R[2][2] = u[2]*u[2] + (u[0]*u[0] + u[1]*u[1])*ca;
    R[2][3] = (c[2]*(u[0]*u[0]+u[1]*u[1])-u[2]*(c[0]*u[0]+c[1]*u[1]))*(1.0 - ca) + (c[0]*u[1] - c[1]*u[0])*sa;

    R[3][0] = 0.0;
    R[3][1] = 0.0;
    R[3][2] = 0.0;
    R[3][3] = 1.0;
}

void dvecnrm(double *v)
{
   double vl;
   int j;

   vl = dveclen(v);
   if (vl != 0.0) {
      for (j=0; j<3; j++) {
	v[j] = v[j] / vl;
      }
   }
}
   
void xyzROT3(R,vt)
double R[4][4];
float *vt;
{
   int j,k;
   double p[3],pp[3];

   for (j=0; j<3; j++) {
	p[j] = vt[j];
	pp[j] = 0.0;
   }

   for (j=0; j<3; j++) {
	for (k=0; k<3; k++) {
	   pp[j] = pp[j] + R[j][k]*p[k];
	}
   }

   for (j=0; j<3; j++) {
	vt[j] = (float) pp[j];
   }
}

void xyzROT4(R,vt)
double R[4][4];
float *vt;
{
   int j,k;
   double p[4],pp[4];

   for (j=0; j<3; j++) {
	p[j] = vt[j];
	pp[j] = 0.0;
   }

   p[3] = 1.0;
   for (j=0; j<3; j++) {
	for (k=0; k<4; k++) {
	   pp[j] = pp[j] + R[j][k]*p[k];
	}
   }

   for (j=0; j<3; j++) {
	vt[j] = (float) pp[j];
   }
}

void OHreal(Tri2)
TRISTRU *Tri2;
{
   int j,i;
   for (j=0; j<3; j++) {
     if (Tri2->ohlig[j] == 1) {
	i = Tri2->lig[j];
	OHRot(Tri2,ligtyp[i]->atom[2],ligtyp[i]->atom[1],ligtyp[i]->atom[0],j);
	OHFnd(Tri2,inttyp[Tri2->prot[j]]->ORI,j);
     }
   }
}

void Trans_Coo(Tri2,coo)
TRISTRU *Tri2;
double *coo;
{
   int i,j;
   float pt[3];
   double R1[4][4],R2[4][4],R3[4][4],t[3];

   if (!allConf(&Tri2->coo,ndocka)) exit(-1);

   for (j = 0; j<3; j++ ) {
      t[j] = Tri2->t[j];
   }

   Trans_Trans(Tri2,coo);

   for (j = 0; j<3; j++ ) {
      t[j] = Tri2->t[j];
   }


   for (i=0; i<ndocka; i++) {
     for (j=0; j<3; j++) {
	Tri2->coo[i*3+j] = t[j] + coo[i*3+j];
     }
   }

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) R1[i][j] = Tri2->R1[i][j];

   for (i=0; i<ndocka; i++) {
     for (j=0; j<3; j++) {
	pt[j] = Tri2->coo[i*3+j];
     }

     xyzROT4(R1,pt);

     for (j=0; j<3; j++) {
	Tri2->coo[i*3+j] = pt[j];
     }
   }

   if (Tri2->oneline) return;

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) R2[i][j] = Tri2->R2[i][j];


   for (i=0; i<ndocka; i++) {
     for (j=0; j<3; j++) {

	pt[j] = (float) Tri2->coo[i*3+j];
     }

     xyzROT4(R2,pt);

     for (j=0; j<3; j++) {
	Tri2->coo[i*3+j] = (double) pt[j];
     }
   }

   OHreal(Tri2);

}

void PrtTrp(int indx)
{
fprintf(stderr,"Triplet %d lig %d %d %d prot %d %d %d conf %d\n",indx,
		TriArr[indx]->lig[0],TriArr[indx]->lig[1],TriArr[indx]->lig[2],
		TriArr[indx]->prot[0],TriArr[indx]->prot[1],TriArr[indx]->prot[2],
		TriArr[indx]->conf);
fprintf(stderr,"prot dist d12 %f d13 %f d23 %f\n",
		TriArr[indx]->d12,TriArr[indx]->d13,TriArr[indx]->d23);

fprintf(stderr,"grp %d %d %d\n",
		TriArr[indx]->grp[0],TriArr[indx]->grp[1],TriArr[indx]->grp[2]);
}

void Compress_Tri_L()
{
   int i,ntritmp,tut,n;
   double dd;

   ntritmp = -1;

   for (i = 0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		ntritmp++;
		TriArrCopy[ntritmp] = TriArr[i];
	   }
	}
   }

   ntritmp++;
   ntris = ntritmp;

   for (i = 0; i < ntris; i++) {
	TriArr[i] = TriArrCopy[i];
   }
}

void Compress_Tri_List()
{
   int i,ntritmp,tut,n;
   double dd;

   if (ntris < MAXSOL) return;
   if (HAS_SPEC) return;

   ntritmp = -1;

   n = ntris+1;
   tut = (ntris+1) % 2;
   if (tut > 0) n--;

   for (i = 0; i < n; i = i + 2 ) {
	if (TriArr[i] == NULL && TriArr[i+1] != NULL) {
	   ntritmp++;
	   TriArrCopy[ntritmp] = TriArr[i+1];
	   continue;
	}
	if (TriArr[i] != NULL && TriArr[i+1] == NULL) {
	   ntritmp++;
	   TriArrCopy[ntritmp] = TriArr[i];
	   continue;
	}
	if (TriArr[i] == NULL) continue;
	if (TriArr[i+1] == NULL) continue;
	if (i+1 < ntris) {
	   if (TriArr[i] != NULL && TriArr[i+1] != NULL) {
		if (TriArr[i]->coo == NULL || TriArr[i+1]->coo == NULL) continue;
	   }
	   dd = dst(TriArr[i],TriArr[i+1]);
	   if (dd <= 0.000001) {
	    TriCooSafeFree(i+1);
	    TriSafeFreeTxt(i+1,"Compress_Tri_List","Reason: dist < 0.000001");
	    ntritmp++;
	    TriArrCopy[ntritmp] = TriArr[i];
	    TriArr[i] = NULL;
	   } else {
	    ntritmp++;
	    TriArrCopy[ntritmp] = TriArr[i];
	    TriArr[i] = NULL;
	    ntritmp++;
	    TriArrCopy[ntritmp] = TriArr[i+1];
	    TriArr[i+1] = NULL;
	   }
	}
   }

   ntris = ntritmp;

   for (i = 0; i < ntris+1; i++) {
	TriArr[i] = TriArrCopy[i];
   }
}

void Compress_Tri_List_dist_nocoo(double dcntcut)
{
   int i,ntritmp,n;
   double dd;
   char TMPs[MAXPATHLEN] = " ";

   ntritmp = -1;

   n = ntris;
   for (i = 0; i < n; i++) {
	if (TriArr[i] != NULL) {
		if (TriArr[i]->dcnt < dcntcut) {
		   ntritmp++;
		   TriArrCopy[ntritmp] = TriArr[i];
		} else {
		   TriCooSafeFree(i);
		   sprintf(TMPs,
			"Triangle Flex Interaction TriArr[]->dcnt > %.3f",
			dcntcut);
		   TriSafeFreeTxt(i,"Compress_Tri_List_dcnt_nocoo",TMPs);
		}
	}
   }

   ntritmp++;

   ntris = ntritmp;
   for (i = 0; i < ntris; i++) {
	TriArr[i] = TriArrCopy[i];
   }
}

void Compress_Tri_List_e12_nocoo()
{
   int i,ntritmp,n;
   double dd;

   ntritmp = -1;

   n = ntris;
   for (i = 0; i < n; i++) {
	if (TriArr[i] != NULL) {
		if (TriArr[i]->e12 < 0.0 || TriArr[i]->oneline) {
		   ntritmp++;
		   TriArrCopy[ntritmp] = TriArr[i];
		} else {
		   TriCooSafeFree(i);
		   TriSafeFreeTxt(i,"Compress_Tri_List_e12_nocoo",
		     "Triangle Flex Interaction TriArr[]->e12 > 0.0");
		}
	}
   }

   ntritmp++;

   ntris = ntritmp;
   for (i = 0; i < ntris; i++) {
	TriArr[i] = TriArrCopy[i];
   }
}

void Compress_Tri_List_e12()
{
   int i,ntritmp,n;
   double dd;

   ntritmp = -1;

   if (debugdck) fprintf(stderr,"before Compress_Tri_List_e12 ntris %d\n",ntris);
   n = ntris;
   for (i = 0; i < n; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		if (TriArr[i]->e12 < 0.0 || 
			(TriArr[i]->spec && TriArr[i]->oneline)) {
		   ntritmp++;
		   TriArrCopy[ntritmp] = TriArr[i];
		}
	   }
	}
   }

   ntritmp++;

   ntris = ntritmp;
   for (i = 0; i < ntris; i++) {
	TriArr[i] = TriArrCopy[i];
   }
   if (debugdck) fprintf(stderr,"Compress_Tri_List_e12 ntris %d\n",ntris);
}


static float E12min = BIGD;

int CalcOne(int itri)
{

// Calculates FlexX interaction energy of one pose:

    int i,j,lj;
    float etot;

    if (TriArr[itri] != NULL) {
	   
	   etot = 0.0;

	   for (j=0; j < 3; j++) {
		lj = TriArr[itri]->lig[j];
 		etot = etot + 
			CalInt(TriArr[itri]->prot[j],lj,ligtyp[lj]->points,
				TriArr[itri]->t,
				TriArr[itri]->R1,TriArr[itri]->R2,
				TriArr[itri]->OutO,TriArr[itri]->OutOrg,0);
	   }

	   TriArr[itri]->e12 = etot;

	   if (etot < E12min) {
		E12min = etot;
//	        if (Match_tri(TriArr[itri],8,24,13,51,235,145)) return(0);
	   } else {
		if (etot > E12min + E12WIN) return(1);
	   }

    }

    return(0);
}

int CalcOne_Spec(int itri)
{

// Calculates FlexX interaction energy of one pose:
// calculates TriArr[itri]->e12 = etot;

    int i,j,lj;
    float etot;

    if (TriArr[itri] != NULL) {
	   
	   etot = 0.0;

	   for (j=0; j < 3; j++) {
		lj = TriArr[itri]->lig[j];
 		etot = etot + 
			CalInt_Spec(TriArr[itri]->prot[j],lj,ligtyp[lj]->points,
				TriArr[itri]->t,
				TriArr[itri]->R1,TriArr[itri]->R2,
				TriArr[itri]->OutO,TriArr[itri]->OutOrg,
				TriArr[itri]->spec,0);
	   }

	   TriArr[itri]->e12 = etot;

	   if (etot < E12min) {
		E12min = etot;
//	        if (Match_tri(TriArr[itri],8,24,13,51,235,145)) return(0);
	   } else {
		if (etot > E12min + E12WIN) return(1);
	   }

    }

    return(0);
}

#define NOLINKCUTOFFLOW 1000
#define NOLINKCUTOFFMED 2000
#define NOLINKCUTOFFHIGH 16000

int FilterFlexTri()
{
// scans ligand + protein combo of triangles, 
// and throws away all but lowest e12

   int i,fnd,lig[3],prot[3],imin,Ntris;
   float Emin;

   Emin = BIGD;
   imin = -1;
   Ntris = ntris;
   fnd = 0;

   for (i=0; i < 3; i++) {
	lig[i]  = -1;
	prot[i] = -1;
   }

   for (i=0; i < Ntris; i++) {
     if (TriArr[i] != NULL) {

	if (fnd == 0 && !TriArr[i]->done) {
	   lig[0] = TriArr[i]->lig[0];
	   lig[1] = TriArr[i]->lig[1];
	   lig[2] = TriArr[i]->lig[2];
	   prot[0] = TriArr[i]->prot[0];
	   prot[1] = TriArr[i]->prot[1];
	   prot[2] = TriArr[i]->prot[2];
	   imin = i;
	   fnd = 1;
	}

	if (fnd) {
	  if (TriArr[i]->lig[0] == lig[0] && 
	      TriArr[i]->lig[1] == lig[1] &&
	      TriArr[i]->lig[2] == lig[2]) {

	    if (TriArr[i]->prot[0] == prot[0] && 
	        TriArr[i]->prot[1] == prot[1] &&
	        TriArr[i]->prot[2] == prot[2]) {

		if (TriArr[i]->e12 < Emin) {
		   Emin = TriArr[i]->e12;
		   imin = i;
		}
	    }
	  }
	}

     }
   }

   if (fnd == 0) return(0);

   for (i=0; i < Ntris; i++) {
     if (TriArr[i] != NULL) {
	if (TriArr[i]->lig[0] == lig[0] && 
	    TriArr[i]->lig[1] == lig[1] &&
	    TriArr[i]->lig[2] == lig[2]) {

	    if (TriArr[i]->prot[0] == prot[0] && 
	        TriArr[i]->prot[1] == prot[1] &&
	        TriArr[i]->prot[2] == prot[2]) {
		if (i != imin) {
		   TriCooSafeFree(i);
		   TriSafeFreeTxt(i,"FilterFlexTri",
			"because does NOT satisfy base ligand combo");
		   ntris--;
		} else {
		   TriArr[i]->done = 1;
		}
	    }
	}
     }
   }

   Compress_Tri_L();

   return(1);
}

int CountOneline()
{
  int i,n;

  n = 0;
  for (i = 0; i < ntris; i++) {
    if (TriArr[i] != NULL) {
       if (TriArr[i]->oneline) n++;
    }
  }

  return(n);
}

void DelAllButOneline()
{
  int i;

  for (i = 0; i < ntris; i++) {
    if (TriArr[i] != NULL) {
        if (!TriArr[i]->oneline) {
	   TriArr[i] = NULL;
	}
    }
  }

}

void OrderDist()
{
  int i,j,n;
  double CNT[3],tt,dst;

  for (i = 0; i < ntris; i++) {
    if (TriArr[i] != NULL) {
	CNT[0] = 0.0; CNT[1] = 0.0; CNT[2] = 0.0;
        tt = 0.0;

	if (TriArr[i]->oneline) {
           for (j = 0; j < 3; j++) {
		CNT[j] = CNT[j] + TriArr[i]->p1c[j];
		CNT[j] = CNT[j] + TriArr[i]->p2c[j];
           }
           for (j = 0; j < 3; j++) {
		CNT[j] = CNT[j]/2.0;
	   }
	} else {
           for (j = 0; j < 3; j++) {
		CNT[j] = CNT[j] + TriArr[i]->p1c[j];
		CNT[j] = CNT[j] + TriArr[i]->p2c[j];
		CNT[j] = CNT[j] + TriArr[i]->p3c[j];
           }
           for (j = 0; j < 3; j++) {
		CNT[j] = CNT[j]/3.0;
	   }
	}
        for (j = 0; j < 3; j++) {
           dst = DCKCNT[j] - CNT[j];
           dst = dst *dst;
           tt = tt + dst;
        }
        TriArr[i]->dcnt = (float) tt;
    }
  }

  if (ntris > 0) {
     qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpd);
  }

//  Compress_Tri_List_dist_nocoo(70.0);
}

int CalcSingleE12(i)
int i;
{
    int j,lj;
    float etot;

    if (TriArr[i] != NULL) {
	   
	   TriArr[i]->done = 0;

	   etot = 0.0;

	   if (TriArr[i]->spec) {
		for (j=0; j < 2; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt_Spec(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,0);
		}
	   }


//	   TriArr[i]->e12 = etot;
	   TriArr[i]->e12 = -10.0;

    }
}

int CalcE12()
{
    int i,j,lj,lig[3],frag;
    float etot,emin;

    emin = 10000.0;
    frag = -1;

//    e12_calculated = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   
	   TriArr[i]->done = 0;

	   etot = 0.0;

	   if (TriArr[i]->spec) {
		for (j=0; j < 2; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,0);
		}
	   } else {
		for (j=0; j < 3; j++) {
		   lj = TriArr[i]->lig[j];

 		   etot = etot + 
			CalInt(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,1);
		}
	   }


	   TriArr[i]->e12 = etot;

	   if (etot < emin) {
		emin = etot;
		frag = TriArr[i]->frag;
		lig[0] = TriArr[i]->lig[0];
		lig[1] = TriArr[i]->lig[1];
		lig[2] = TriArr[i]->lig[2];
	   }

	}
    }
    return(frag);
}

int CalcE12_Spec()
{
    int i,j,lj,lig[3],frag;
    float etot,emin;

    emin = 10000.0;
    frag = -1;

//    e12_calculated = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   
	   TriArr[i]->done = 0;

	   etot = 0.0;

	   if (TriArr[i]->spec) {
		for (j=0; j < 2; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt_Spec(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,0);
		   if (TriArr[i]->oneline) etot = -20;
		}
	   } else {
		for (j=0; j < 3; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt_Spec(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,0);
		}
	   }


	   TriArr[i]->e12 = etot;

	   if (etot < emin) {
		emin = etot;
		frag = TriArr[i]->frag;
		lig[0] = TriArr[i]->lig[0];
		lig[1] = TriArr[i]->lig[1];
		lig[2] = TriArr[i]->lig[2];
	   }

	}
    }
    return(frag);
}

void Copy_OH(double *coo1,double *coo2,
	int lig1,int lig2,int lig3,
	int doflip1,int doflip2,int doflip3)
{
   int i,j;

// copy coo1 to coo2

   for (i=0; i < ndocka; i++) {
	for (j=0; j < 3; j++) {
	   coo2[i*3+j] = coo1[i*3+j];
	}
   }

   if (doflip1) {
      OHGRot(coo2,
	ligtyp[lig1]->atom[2],ligtyp[lig1]->atom[1],ligtyp[lig1]->atom[0],
	180);
   }

   if (doflip2) {
      OHGRot(coo2,
	ligtyp[lig2]->atom[2],ligtyp[lig2]->atom[1],ligtyp[lig2]->atom[0],
	180);
   }

   if (doflip3) {
      OHGRot(coo2,
	ligtyp[lig3]->atom[2],ligtyp[lig3]->atom[1],ligtyp[lig3]->atom[0],
	180);
   }
}

void ExpConf(int i, int *ntrisc)
{
    int j,conf,lig,first;

    first = 1;
    lig = TriArr[i]->lig[0];

    for (j=0; j < ligtyp[lig]->nconf; j++) {
	conf = ligtyp[lig]->ConfArr[j];

	if (TriFin[conf] != NULL) {
	   if (Find_Lig_Conf(conf,i)) {
	      if (first) {

		Trans_Coo(TriArr[i],TriFin[conf]->coo);
		TriArr[i]->conf = conf;
		first = 0;

	      } else {

	 	TriAll(&TriArr[*ntrisc]);
		TriArr[*ntrisc]->coo = 
			(double *) malloc(sizeof(double)*ndocka*3);
		memcpy(TriArr[*ntrisc], TriArr[i], sizeof(TRISTRU));
		Trans_Coo(TriArr[*ntrisc],TriFin[conf]->coo);
		TriArr[*ntrisc]->conf = conf;
		first = 0;
		(*ntrisc)++;
	      }
	   }
	}
    }
}

void ExpConf_Spec(double *coo,
	     int lig1,int lig2,int lig3,
	     int doflip1,int doflip2,int doflip3,
	     int i, int *ntrisc)
{
    int j,k,conf,lig,first;
    TRISTRU hlptri;

    first = 1;
    lig = TriArr[i]->lig[0];

    for (j=0; j < ligtyp[TriArr[i]->lig[0]]->nconf; j++) {
	if (ligtyp[TriArr[i]->lig[0]]->ConfArr != NULL) {
	   conf = ligtyp[TriArr[i]->lig[0]]->ConfArr[j];
        } else {
	   conf = 0;
	}

	if (conf < ntrif && conf >= 0) {

	  if (TriFin[conf] != NULL) {
	   if (Find_Lig_Conf(conf,i)) {
	      if (first) {

		hlptri = *TriArr[i];
		TriArr[i]->conf = conf;
	    	Copy_OH(TriFin[conf]->coo,coo,
		   lig1,lig2,lig3,
		   doflip1,doflip2,doflip3);
		Trans_Coo(TriArr[i],coo);
		first = 0;

	      } else {

	 	TriAll(&TriArr[*ntrisc]);
		TriArr[*ntrisc]->coo = 
			(double *) malloc(sizeof(double)*ndocka*3);
		*TriArr[*ntrisc] = hlptri;
		TriArr[*ntrisc]->conf = conf;
		for (k=0; k < 3; k++) {
		   TriArr[*ntrisc]->P1[k] = hlptri.p1[k];
		   TriArr[*ntrisc]->P2[k] = hlptri.p2[k];
		   TriArr[*ntrisc]->P3[k] = hlptri.p3[k];
		}
	    	Copy_OH(TriFin[conf]->coo,coo,
		   lig1,lig2,lig3,
		   doflip1,doflip2,doflip3);
		Trans_Coo(TriArr[*ntrisc],coo);
		first = 0;
		(*ntrisc)++;
	      }
	   }
	  }
	}
    }
}

double DstTwo(int il0,int il1,int type)
{
   int j;
   double c0[3],c1[3],d01,dd;

   dd = 0.0;
   if (type == 0) {
	for (j=0; j < 3; j++) {
	   c0[j] = ligtyp[il0]->c[0][j];
	   c1[j] = ligtyp[il1]->c[0][j];
	   dd = dd + (c0[j]-c1[j])*(c0[j]-c1[j]);
	}
   } else {
	for (j=0; j < 3; j++) {
	   c0[j] = inttyp[il0]->c[0][j];
	   c1[j] = inttyp[il1]->c[0][j];
	   dd = dd + (c0[j]-c1[j])*(c0[j]-c1[j]);
	}
   }
   return(sqrt(dd));
}

void Optimise_Check_overlap()
{
   int i,il0,il1,il2,ip0,ip1,ip2,*iclos;
   float *q,*vdwr,*vdwe,*F;
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   FillOptD(iclos); 

   for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {
	il0 = TriArr[i]->lig[0];
	il1 = TriArr[i]->lig[1];
	il2 = TriArr[i]->lig[2];
	ip0 = TriArr[i]->prot[0];
	ip1 = TriArr[i]->prot[1];
	ip2 = TriArr[i]->prot[2];
	if ((ligtyp[il0]->type == 0 && ligtyp[il1]->type == 1) || 
	    (ligtyp[il0]->type == 1 && ligtyp[il1]->type == 0)) {
	   if ((inttyp[ip0]->type == 0 && inttyp[ip1]->type == 1) || 
	       (inttyp[ip0]->type == 1 && inttyp[ip1]->type == 0)) {
		if (ligtyp[il2]->type == 9 && inttyp[ip2]->type == 9) {
		   if (DstTwo(TriArr[i]->lig[0],TriArr[i]->lig[1],0) < 4.8) {
			if (DstTwo(TriArr[i]->prot[0],TriArr[i]->prot[1],1) < 4.8) {
			   Optimise_Overlap(i,vdwr,vdwrl);
			   Optimise_Energy(i,0,q,
				vdwe,vdwr,ql,vdwel,vdwrl,iclos);
			   Optimise_Energy(i,1,
				q,vdwe,vdwr,ql,vdwel,vdwrl,iclos);
			}
		   }
	   	}
	   }
        }
      }
   }

   free(vdwr);
   free(vdwe);
   free(q);
   free(iclos);
   free(F);
}

void Print_Data()
{
  fprintf(stderr,"\n     ######################################\n");
  fprintf(stderr,"     # Number of Ligand Triplets %7d  #\n",ntris);
  if (FASTSLOW) {
     fprintf(stderr,"     # Economic run                       #\n");
  } else {
     fprintf(stderr,"     # Quality  run                       #\n");
  }
  if (HAS_SPEC) {
     fprintf(stderr,"     # Special Case:                      #\n");
     fprintf(stderr,"     # A pair of Acceptors/Donors found   #\n"); 
  }
  fprintf(stderr,"     # Docking Deviation: %.2f            #\n",DCKdev);
  fprintf(stderr,"     ######################################\n\n");
}

int CalcSchIntOld(int nolink)
{
    int i,j,lj,lig[3],ido,idoc,frag,conf,ntriso,NtrisCut,ntrisc,first,fnd,itry;
    float etot,emin;

    emin = 10000.0;
    frag = -1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   
	   TriArr[i]->done = 0;

	   etot = 0.0;

	   if (TriArr[i]->spec) {
		for (j=0; j < 2; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt_Spec(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,0);
		}
	   } else {
		for (j=0; j < 3; j++) {
		   lj = TriArr[i]->lig[j];
 		   etot = etot + 
			CalInt_Spec(TriArr[i]->prot[j],lj,ligtyp[lj]->points,
				TriArr[i]->t,
				TriArr[i]->R1,TriArr[i]->R2,
				TriArr[i]->OutO,TriArr[i]->OutOrg,
				TriArr[i]->spec,0);
		}
	   }


	   TriArr[i]->e12 = etot;

	   if (etot < emin) {
		emin = etot;
		frag = TriArr[i]->frag;
		lig[0] = TriArr[i]->lig[0];
		lig[1] = TriArr[i]->lig[1];
		lig[2] = TriArr[i]->lig[2];
	   }

	}
    }

    if (!MapConformers && e12_calculated) {
	while (FilterFlexTri()) {}
    }

    Compress_Tri_List_e12_nocoo();

    if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptri);
    }

    if (nolink) ntris = NOLINKCUTOFFLOW;

fprintf(stderr,"CalcSchIntold: ntris %d nolink %d\n",ntris,nolink);

    NtrisCut = -1;
    ntrisc = ntris;

    if (ntris == -1) return(frag);


    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {

	ido = 0; idoc = 0; conf = -1; itry = -1;
	if (TriArr[i]->conf != -1) idoc = 1;
	if (idoc) {
	   conf = TriArr[i]->conf;
	   itry = TriArr[i]->itry;
	} else {
	   if (TriArr[i]->frag == frag) ido = 1;
	}

	if (TriArr[i]->e12 > TriArr[0]->e12 + E12WIN) {
	   if (NtrisCut == -1) NtrisCut = i;
	   ido = 0; idoc = 0;
	}

	if (ido) {
	    TriArr[i]->conf = 0;
	    Trans_Coo(TriArr[i],DCKxyz.coo);
	} else if (idoc) {
	    if (TriArr[i]->nconf == 0) {
		if (TriFin[conf] != NULL) {
		   TriArr[i]->conf = 0;
		   Trans_Coo(TriArr[i],TriFin[conf]->coo);
		}
		continue;
	    }

	    first = 1;
	    for (j=0; j < ligtyp[TriArr[i]->lig[0]]->nconf; j++) {
		conf = ligtyp[TriArr[i]->lig[0]]->ConfArr[j];

		if (TriFin[conf] != NULL) {
		   if (Find_Lig_Conf(conf,i)) {
		      if (first) {
			TriArr[i]->conf = conf;
			Trans_Coo(TriArr[i],TriFin[conf]->coo);
			TriArr[i]->itry = itry;
			first = 0;
		      } else {
	   		TriAll(&TriArr[ntrisc]);
			TriArr[ntrisc]->coo = 
			(double *) malloc(sizeof(double)*ndocka*3);
			memcpy(TriArr[ntrisc], TriArr[i], sizeof(TRISTRU));
			TriArr[ntrisc]->conf = conf;
			Trans_Coo(TriArr[ntrisc],TriFin[conf]->coo);
			TriArr[ntrisc]->itry = itry;
			ntrisc++;
		      }
		   }
		}
	    }

	} else {
	    if (TriArr[i] != NULL) {
	        TriCooSafeFree(i);
	        TriSafeFreeTxt(i,"CalcSchInt",
		  "CalcSchInt: triangle does NOT satisfy base ligand combo");
	    }
	}
      }
    }

    if (ntrisc > ntris) ntris = ntrisc;

    Print_Data();

    ntriso = -1;

    for (i=0; i < 10; i++) {
	Compress_Tri_List();
	if ( ntris == ntriso || ntris == 1) break;
	ntriso = ntris;
//        fprintf(stderr,"compressed ntris %d\n",ntris);
    }


if (debugdck) Write_Results("calcschinta.mol2",TriArr,ntris,&DCKxyz,1,0);

    return(frag);
}


int ChkOH(int lig,int Tabel[100][3],int nlig)
{
   int i;

// What if all of these need to be flipped ??
// Tabel contains all interaction points that have flipped locations

   for (i=0; i<nlig; i++) {
      if (lig == Tabel[i][0] || lig == Tabel[i][1] || lig == Tabel[i][2]) {
	if (lig == Tabel[i][1]) return(1);
	if (lig == Tabel[i][2]) return(2);
      }
   }
   return(0);
}

void ScanLigTyp(int Tabel[100][3],int *n)
{
   int i,ido;

   *n = 0;
   for (i=0; i<100; i++) {
	Tabel[i][0] = -1; Tabel[i][1] = -1; Tabel[i][2] = -1;
   }

   for (i=0; i<lintp-3; i++) {
	if (ligtyp[i]->type == H_DON && ligtyp[i+1]->type == H_DON) {
           ido = 0;
	   if (ABS(ligtyp[i]->ohsame) == ABS(ligtyp[i+1]->ohsame)) {
		Tabel[*n][0] = i; Tabel[*n][1] = i+1; Tabel[*n][2] = -1;
		ido = 1;
	   }
	   if (ido == 1) {
	      if (*n < 99) {
	        (*n)++;
   	      } else {
		break;
	      }
	   }
	}
	if (ligtyp[i]->type == H_DON && ligtyp[i+1]->type == H_DON &&
		ligtyp[i+2]->type == H_DON) {
           ido = 0;
	   if (ABS(ligtyp[i]->ohsame) == ABS(ligtyp[i+1]->ohsame) &&
		ABS(ligtyp[i]->ohsame) == ABS(ligtyp[i+2]->ohsame) ){
		Tabel[*n][0] = i; Tabel[*n][1] = i+1; Tabel[*n][2] = i+2;
		ido = 1;
	   }
	   if (ido == 1) {
	      if (*n < 99) {
	        (*n)++;
   	      } else {
		break;
	      }
	   }
	}
   }

}

int CalcSchInt(int nolink)
{
    int i,j,lj,n,lig[3],ido,idoc,frag,conf,ntriso,NtrisCut,ntrisc,first,fnd;
    int ligselp;
    float etot,emin;


    frag = 0;
    OrderDist();

    if (nolink) {
	if (ntrif <= 8) {
	   ntris = NOLINKCUTOFFHIGH;
	} else {
	   ntris = NOLINKCUTOFFLOW;
	}
    }

    NtrisCut = -1;
    ntrisc = ntris;

    if (ntris == -1) return(frag);

    frag = CalcE12();

    if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptri);
    }

    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {

	ido = 0; idoc = 0; conf = -1;
	if (TriArr[i]->conf != -1) idoc = 1;

	if (idoc) {
	   conf = TriArr[i]->conf;
	} else {
	   if (TriArr[i]->frag == frag) ido = 1;
	}

	if (TriArr[i]->e12 > TriArr[0]->e12 + E12WIN) {
	   if (NtrisCut == -1) NtrisCut = i;
	   ido = 0; idoc = 0;
	}

	if (ido) {
	    Trans_Coo(TriArr[i],DCKxyz.coo);
	    TriArr[i]->conf = 0;
	} else if (idoc) {
	    if (TriArr[i]->nconf == 0) {
		if (TriFin[conf] != NULL) Trans_Coo(TriArr[i],TriFin[conf]->coo);
		continue;
	    }

	    ExpConf(i,&ntrisc);

	} else {
	    if (TriArr[i] != NULL) {
	        TriCooSafeFree(i);
	        TriSafeFreeTxt(i,"CalcSchInt",
		  "CalcSchInt: triangle does NOT satisfy base ligand combo");
	    }
	}
      }
    }


    if (ntrisc > ntris) ntris = ntrisc;

// calculate e12 of added conformations

    Print_Data();

    frag = CalcE12();

    if (!MapConformers && e12_calculated) {
	while (FilterFlexTri()) {}
    }

    Compress_Tri_List_e12_nocoo();

    if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptri);
    }

    ntriso = -1;

    if (ntrif > 8) {
	for (i=0; i < 10; i++) {
	   Compress_Tri_List();
	   if ( ntris == ntriso || ntris == 1) break;
	   ntriso = ntris;
           fprintf(stderr,"compressed ntris %d\n",ntris);
	}
    }

    if (ntrif <= 8 && ntrif != -1) {
	if (DCKMETH == 0) {
	   Calc_Overlap2();
	} else {
	   Calc_Overlap();
	}

	Optimise_Check_overlap();

	if (ntris > 0) {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpover);
	}

	n = -1;
	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
		if (TriArr[i]->overl >= 2.0) {
	           TriCooSafeFree(i);
	           TriSafeFreeTxt(i,"CalcSchInt",
		     "CalcSchInt: overl cutoff 2.0");
		} else {
		   n = i;
		}
	   }
	}
        ntris = n+1;
    }

if (debugdck) Write_Results("calcschintb.mol2",TriArr,ntris,&DCKxyz,1,0);

    return(frag);
}

float Get_E12_0()
{
   float E12;
   int i;

   E12 = BIGD;

   for (i=0; i < 10; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		E12 = TriArr[i]->e12;
	   }
	}
   }

   return E12;

}

int CalcSchInt_Spec(int nolink)
{
    int i,j,lj,n,nlig,lig[3],ido,idoc,frag,conf,ligselp;
    int ntriso,NtrisCut,ntrisc,first,fnd,size;
    int start, Tabel[100][3], doflip[3];
    float etot,emin,E12;

    size = MXLIGA;
    alldck(&DCKtmp,&size);

    n = CountOneline();
    if ( n == 0 ) {
	OrderDist();
    }

    ligselp = LigSel - 1;

    if (nolink) {
	if (ntrif <= 8) {
	   if (strcmp(pdbcode,"3k3e") == 0
		&& strcmp(hetptr.HetAtm[ligselp],"PDB") == 0) {
		ntris = 20000;
		fprintf(stderr,"Changed NOLINKCUTOFFLOW from %d to 20000\n",
			NOLINKCUTOFFHIGH);
	   } else {
	   	ntris = NOLINKCUTOFFHIGH;
	        if (strcmp(pdbcode,"1a28") == 0) {
//		    ntris = 10000;
	        }
	   }
	} else {
	   if ((strcmp(pdbcode,"7ndo") == 0 || strcmp(pdbcode,"2qxs") == 0 )
		&& strcmp(hetptr.HetAtm[ligselp],"RAL") == 0) {
		ntris = 7000;
		fprintf(stderr,"Changed NOLINKCUTOFFLOW from %d to 7000\n",
			NOLINKCUTOFFLOW);
	   } else {
	   	ntris = NOLINKCUTOFFLOW;
	   }
	}
    }


    if (n>0) {
	DelAllButOneline();
    }
fprintf(stderr,"CalcSchInt_Spec after DelAllButOneline ntris %d\n",ntris);
	   
    ScanLigTyp(Tabel,&nlig);

    NtrisCut = -1;
    ntrisc = ntris;

    if (ntris == -1) return(frag);

    frag = CalcE12_Spec();

    E12 = Get_E12_0();

    if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptri);
    }

fprintf(stderr,"CalcSchInt_Spec beforr ChkOH ntris %d\n",ntris);
	   
    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {

	doflip[0] = ChkOH(TriArr[i]->lig[0],Tabel,nlig);
	doflip[1] = ChkOH(TriArr[i]->lig[1],Tabel,nlig);
	doflip[2] = ChkOH(TriArr[i]->lig[2],Tabel,nlig);

	ido = 0; idoc = 0; conf = -1;
	if (TriArr[i]->conf != -1) idoc = 1;

	if (idoc) {
	   conf = TriArr[i]->conf;
	} else {
	   if (TriArr[i]->frag == frag) ido = 1;
	}

	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		if (TriArr[i]->e12 > E12 + E12WIN) {
			if (NtrisCut == -1) NtrisCut = i;
			ido = 0; idoc = 0;
	   	}
	   }
	}

	if (ido) {

	   if (TriArr[i] != NULL) {
		if (TriArr[i]->coo != NULL) {
		   if (TriArr[i]->e12 > E12 + E12WIN) {
	 		TriArr[i]->conf = 0;

			Copy_OH(DCKxyz.coo,DCKtmp.coo,
			TriArr[i]->lig[0],TriArr[i]->lig[1],TriArr[i]->lig[2],
			doflip[0],doflip[1],doflip[2]);
	    		Trans_Coo(TriArr[i],DCKtmp.coo);
		   }
		}
	   }

	} else if (idoc) {
	    if (TriArr[i]->nconf == 0) {
		TriArr[i]->conf = conf;
		if (TriFin[conf] != NULL) {
		   if (TriArr[i]->coo != NULL) {
	    		Copy_OH(TriFin[conf]->coo,DCKtmp.coo,
			TriArr[i]->lig[0],TriArr[i]->lig[1],TriArr[i]->lig[2],
			doflip[0],doflip[1],doflip[2]);
			Trans_Coo(TriArr[i],DCKtmp.coo);
		   }
		}
		continue;
	    }

	    ExpConf_Spec(DCKtmp.coo,
		    TriArr[i]->lig[0],TriArr[i]->lig[1],TriArr[i]->lig[2],
		    doflip[0],doflip[1],doflip[2],
		    i,&ntrisc);

	} else {
	    if (TriArr[i] != NULL) {
	     if (TriArr[i]->coo != NULL) {
	        TriCooSafeFree(i);
	        TriSafeFreeTxt(i,"CalcSchInt",
		  "CalcSchInt: triangle does NOT satisfy base ligand combo");
	     }
	    }
	}
      }
    }

    if (ntrisc > ntris) ntris = ntrisc;

    if (strcmp(pdbcode,"3k3e") == 0
		&& strcmp(hetptr.HetAtm[ligselp],"PDB") == 0) {
	ntris = 2300;
    }

    Print_Data();

// calculate e12 of added conformations

    frag = CalcE12_Spec();

    if (!MapConformers && e12_calculated) {
	while (FilterFlexTri()) {}
    }

//    Compress_Tri_List_e12_nocoo();

    if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmptri);
    }

    ntriso = -1;

    if (ntrif > 8) {
	  for (i=0; i < 10; i++) {
	   Compress_Tri_List();
	   if ( ntris == ntriso || ntris == 1) break;
	   ntriso = ntris;
//         fprintf(stderr,"compressed ntris %d\n",ntris);
	  }
    }

    if ((ntrif <= 8 && ntrif != -1) && 
	(strcmp(pdbcode,"1a28") == 0 || strcmp(pdbcode,"3k3e") == 0)
    ) {

	if (DCKMETH == 0) {
	   Calc_Overlap2();
	} else {
	   Calc_Overlap();
	}

	Optimise_Check_overlap();

	if (ntris > 0) {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpover);
	}

	n = -1;
	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
	     if (TriArr[i]->coo != NULL) {
		   if (TriArr[i]->overl >= 2.0) {
			TriCooSafeFree(i);
			TriSafeFreeTxt(i,"CalcSchInt",
				"CalcSchInt: overl cutoff 2.0");
		   } else {
		   	n = i;
		   }
	     }
	   }
	}
        ntris = n+1;
    }
if (debugdck) Write_Results("calcschintc.mol2",TriArr,ntris,&DCKxyz,1,0);

    return(frag);
}

void TransForm_Tri3(Tri)
TRISTRU *Tri;
{
   int i,j,k,l,spec,type[3],typtot,iset,fnd;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float x,y,z,pt[3],pl,COSA,SINA,cosa,sina;
   float cooTri1AD0[3],cooTri1AD1[3];
   float cooTri2AD0[3],cooTri2AD1[3];
   double R1[4][4],R2[4][4],t[3];
   TRISTRU Tri0;

// calculate rotation matrix to rotate around the out-vector
// of the triangle if all three sides as more or less equal

   Tri0 = *Tri;
   if (Tri0.spec) return;

   spec = 0; type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
   iset = -1;

/* Tri0 is original, Tri to be transformed Tri0 */

/* check for 2x H_DON/H_ACC + 1 != H_DON/H_ACC */

   for (j = 0; j<3; j++ ) {
	if (ligtyp[Tri0.lig[j]]->type == H_ACC ||
		ligtyp[Tri0.lig[j]]->type == H_DON) {
	   type[j] = 1;
	} else {
	   type[j] = 0;
	}
	typtot = typtot + type[j];
   }

   if (typtot == 3 || typtot == 0) {

	type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;

	for (j = 0; j<3; j++ ) {
	    fnd = 0;

if (Tri0.lig[j] < lintp && Tri0.prot[j] < nintp) {
	    if (ligtyp[Tri0.lig[j]]->area.iden == 3 &&
		inttyp[Tri0.prot[j]]->area.iden == 0) fnd = 1;
	    if (ligtyp[Tri0.lig[j]]->area.iden == 0 ||
		inttyp[Tri0.prot[j]]->area.iden == 3) fnd = 1;

	    if (ligtyp[Tri0.lig[j]]->q1 == 0.333 ||
		inttyp[Tri0.prot[j]]->q1 == 0.333) fnd = 1;
	    if (fnd) {
		type[j] = 1;
	    } else {
		type[j] = 0;
	    }
}

	    typtot = typtot + type[j];
	}

	if (typtot == 3) {

	   spec = 3;
	   if (!HAS_SPEC) HAS_SPEC = 3;
	   Tri->spec = spec;
	}

   }

   vecnrm(Tri->Out);
   vecnrm(Tri0.Out);

   for (j = 0; j<3; j++ ) {
	t[j]    = (double) (Tri0.Cen[j] - Tri->Cen[j]);
	v3[j]   = Tri0.p1[j] - Tri0.Cen[j];
	V1[j]   = Tri->p1[j] - Tri->Cen[j];
	V2[j]   = Tri->Out[j];
	Tri->Cen[j] = Tri->Cen[j] + (float) t[j];
	Tri->p1c[j] = Tri->p1[j] + t[j];
	Tri->p2c[j] = Tri->p2[j] + t[j];
	Tri->p3c[j] = Tri->p3[j] + t[j];
	Tri->P1[j] = Tri0.p1[j];
	Tri->P2[j] = Tri0.p2[j];
	Tri->P3[j] = Tri0.p3[j];
	Tri->t[j] = t[j];
	Tri->CenO[j] = Tri0.Cen[j];
	Tri->OutOrg[j] = Tri0.Out[j];
	Tri->prot[j] = Tri0.prot[j];
	Tri->lig[j] = Tri0.lig[j];
	Tri->ohlig[j] = Tri0.ohlig[j];
   }

// R1 is a unitary matrix (does not do anything)

   for (i=0; i<4; i++ ) {
      for (j=0; j<4; j++ ) {
	if (i == j) {
	   R1[i][j] = 1.0;
	} else {
	   R1[i][j] = 0.0;
	}
      }
   }

   vecnrm(V1);
   
   for (j = 0; j<3; j++ ) {
	Tri->OutO[j] = V2[j];
   }

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri->R1[i][j] = R1[i][j];

   cross(Tri0.Out,v3,v2);

// v2 created out of Tri0.Out and v3
// orthonormal basis Tri.out=z,v2=x,v3=y

   vecnrm(v2);
   vecnrm(v3);
   vecnrm(Tri0.Out);

// created new normalised cartesian axes Tri.out=z,v2=x,v3=y

   vecnrm(V1);
   cross(V2,V1,V3);

   IMPRD(v3,V1,&COSA,1);
   IMPRD(v3,V3,&SINA,1);

   Frst_Rot(Tri->Cen,V2,SINA,COSA,R2);

   xyzROT4(R2,Tri->p1c);
   xyzROT4(R2,Tri->p2c);
   xyzROT4(R2,Tri->p3c);

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri->R2[i][j] = R2[i][j];

}

void TransForm_Tri3to2(Tri)
TRISTRU *Tri;
{
   int i,j,k,l,spec,type[3],typtot,iset,fnd;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float x,y,z,pt[3],pl,COSA,SINA,cosa,sina;
   float cooTri1AD0[3],cooTri1AD1[3];
   float cooTri2AD0[3],cooTri2AD1[3];
   double R1[4][4],R2[4][4],t[3];
   TRISTRU Tri0;

   Tri0 = *Tri;
   if (Tri0.spec) return;

   spec = 0; type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
   iset = -1;

/* Tri0 is original, Tri to be transformed Tri0 */

/* check for 2x H_DON/H_ACC + 1 != H_DON/H_ACC */

   for (j = 0; j<3; j++ ) {
	if (ligtyp[Tri0.lig[j]]->type == H_ACC ||
		ligtyp[Tri0.lig[j]]->type == H_DON) {
	   type[j] = 1;
	} else {
	   type[j] = 0;
	}
	typtot = typtot + type[j];
   }

   if (typtot == 3) {
	type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
	for (j = 0; j<3; j++ ) {
	    fnd = 0;

if (Tri0.lig[j] < lintp && Tri0.prot[j] < nintp) {
	    if (ligtyp[Tri0.lig[j]]->area.iden == 3 &&
		inttyp[Tri0.prot[j]]->area.iden == 0) fnd = 1;
	    if (ligtyp[Tri0.lig[j]]->area.iden == 0 ||
		inttyp[Tri0.prot[j]]->area.iden == 3) fnd = 1;

	    if (ligtyp[Tri0.lig[j]]->q1 == 0.333 ||
		inttyp[Tri0.prot[j]]->q1 == 0.333) fnd = 1;
	    if (fnd) {
		type[j] = 1;
	    } else {
		type[j] = 0;
	    }
}
	    typtot = typtot + type[j];
	}

	if (typtot == 2) {
	   iset = -1;
	   for (j = 0; j<3; j++ ) {
	      if (type[j] == 1) {
		 if (iset == -1) {
		   if (j == 0) {
			cooTri1AD0[0] = Tri0.p1[0];
			cooTri1AD0[1] = Tri0.p1[1];
			cooTri1AD0[2] = Tri0.p1[2];
			cooTri2AD0[0] = Tri->p1[0];
			cooTri2AD0[1] = Tri->p1[1];
			cooTri2AD0[2] = Tri->p1[2];
		   } else if (j == 1) {
			cooTri1AD0[0] = Tri0.p2[0];
			cooTri1AD0[1] = Tri0.p2[1];
			cooTri1AD0[2] = Tri0.p2[2];
			cooTri2AD0[0] = Tri->p2[0];
			cooTri2AD0[1] = Tri->p2[1];
			cooTri2AD0[2] = Tri->p2[2];
		   } else if (j == 2) {
			cooTri1AD0[0] = Tri0.p3[0];
			cooTri1AD0[1] = Tri0.p3[1];
			cooTri1AD0[2] = Tri0.p3[2];
			cooTri2AD0[0] = Tri->p3[0];
			cooTri2AD0[1] = Tri->p3[1];
			cooTri2AD0[2] = Tri->p3[2];
		   }
		   iset = 1;
		 } else {
		   if (iset == 1) {
		   	if (j == 0) {
			   cooTri1AD1[0] = Tri0.p1[0];
			   cooTri1AD1[1] = Tri0.p1[1];
			   cooTri1AD1[2] = Tri0.p1[2];
			   cooTri2AD1[0] = Tri->p1[0];
			   cooTri2AD1[1] = Tri->p1[1];
			   cooTri2AD1[2] = Tri->p1[2];
		   	} else if (j == 1) {
			   cooTri1AD1[0] = Tri0.p2[0];
			   cooTri1AD1[1] = Tri0.p2[1];
			   cooTri1AD1[2] = Tri0.p2[2];
			   cooTri2AD1[0] = Tri->p2[0];
			   cooTri2AD1[1] = Tri->p2[1];
			   cooTri2AD1[2] = Tri->p2[2];
		   	} else if (j == 2) {
			   cooTri1AD1[0] = Tri0.p3[0];
			   cooTri1AD1[1] = Tri0.p3[1];
			   cooTri1AD1[2] = Tri0.p3[2];
			   cooTri2AD1[0] = Tri->p3[0];
			   cooTri2AD1[1] = Tri->p3[1];
			   cooTri2AD1[2] = Tri->p3[2];
		   	}
			iset = 2;
		   }
		 }
	      }
	   }
	   spec = 2;
	   if (!HAS_SPEC) HAS_SPEC = 2;
	}
   }

   if (spec) {
	for (j = 0; j<3; j++ ) {
	   Tri0.Cen[j] = (cooTri1AD0[j] + cooTri1AD1[j])/2.0;
	   Tri->Cen[j] = (cooTri2AD0[j] + cooTri2AD1[j])/2.0;
	}
	Tri->spec = spec;
   }

   for (j = 0; j<3; j++ ) {
	t[j] = (double) (Tri0.Cen[j] - Tri->Cen[j]);
	if (spec) {
	   v3[j] = cooTri1AD0[j] - Tri0.Cen[j];
	   V1[j] = cooTri2AD0[j] - Tri->Cen[j];
	} else {
	   v3[j] = Tri0.p1[j] - Tri0.Cen[j];
	   V1[j] = Tri->p1[j] - Tri->Cen[j];
	}
	V2[j]   = Tri->Out[j];
	Tri->Cen[j] = Tri->Cen[j] + (float) t[j];
	Tri->p1c[j] = Tri->p1[j] + t[j];
	Tri->p2c[j] = Tri->p2[j] + t[j];
	Tri->p3c[j] = Tri->p3[j] + t[j];
	Tri->P1[j] = Tri0.p1[j];
	Tri->P2[j] = Tri0.p2[j];
	Tri->P3[j] = Tri0.p3[j];
	Tri->t[j] = t[j];
	Tri->CenO[j] = Tri0.Cen[j];
	Tri->OutOrg[j] = Tri0.Out[j];
	Tri->prot[j] = Tri0.prot[j];
	Tri->lig[j] = Tri0.lig[j];
	Tri->ohlig[j] = Tri0.ohlig[j];
   }

   vecnrm(Tri->Out);
   vecnrm(Tri0.Out);

   cross(Tri->Out,Tri0.Out,v1);
   cross(Tri0.Out,Tri->Out,v1);
   cross(Tri0.Out,v1,v2);
   
   vecnrm(v1);
   vecnrm(v2);
   
   IMPRD(Tri->Out,Tri0.Out,&cosa,1);
   IMPRD(Tri->Out,v2,&sina,1);

   Frst_Rot(Tri0.Cen,v1,sina,cosa,R1);

   vecnrm(V1);
   vecnrm(V2);
   
   xyzROT3(R1,V1);
   xyzROT3(R1,V2);

   xyzROT4(R1,Tri->p1c);
   xyzROT4(R1,Tri->p2c);
   xyzROT4(R1,Tri->p3c);

   for (j = 0; j<3; j++ ) {
	Tri->OutO[j] = V2[j];
   }

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri->R1[i][j] = R1[i][j];

   cross(Tri0.Out,v3,v2);

/* orthonormal basis Tri.out=z,v2=x,v3=y */

   vecnrm(v2);
   vecnrm(v3);
   vecnrm(Tri0.Out);
   vecnrm(V1);
   cross(V2,V1,V3);

   IMPRD(v3,V1,&COSA,1);
   IMPRD(v3,V3,&SINA,1);

   Frst_Rot(Tri->Cen,V2,SINA,COSA,R2);

   xyzROT4(R2,Tri->p1c);
   xyzROT4(R2,Tri->p2c);
   xyzROT4(R2,Tri->p3c);

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri->R2[i][j] = R2[i][j];

}

void Trans_Trans(Tri2,coo)
TRISTRU *Tri2;
double *coo;
{
   int i,j,k,l,spec,type[3],typtot,iset,fnd;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float cooTri1AD0[3],cooTri1AD1[3];
   float cooTri2AD0[3],cooTri2AD1[3];
   float Cen[3];
   double t[3];

   spec = 0; type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
   iset = -1;

/* check for 2x H_DON/H_ACC + 1 != H_DON/H_ACC */

   for (j = 0; j<3; j++ ) {
	if (ligtyp[Tri2->lig[j]]->type == H_ACC ||
		ligtyp[Tri2->lig[j]]->type == H_DON) {
		type[j] = 1;
		if (iset == -1) {
		   if (j == 0) {
			cooTri1AD0[0] = inttyp[Tri2->prot[0]]->ORI[0];
			cooTri1AD0[1] = inttyp[Tri2->prot[0]]->ORI[1];
			cooTri1AD0[2] = inttyp[Tri2->prot[0]]->ORI[2];

// we need to have the coordinates from the conformer in here

			cooTri2AD0[0] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3];
			cooTri2AD0[1] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3+1];
			cooTri2AD0[2] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3+2];
		   } else if (j == 1) {
			cooTri1AD0[0] = inttyp[Tri2->prot[1]]->ORI[0];
			cooTri1AD0[1] = inttyp[Tri2->prot[1]]->ORI[1];
			cooTri1AD0[2] = inttyp[Tri2->prot[1]]->ORI[2];
			cooTri2AD0[0] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3];
			cooTri2AD0[1] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3+1];
			cooTri2AD0[2] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3+2];
		   } else if (j == 2) {
			cooTri1AD0[0] = inttyp[Tri2->prot[2]]->ORI[0];
			cooTri1AD0[1] = inttyp[Tri2->prot[2]]->ORI[1];
			cooTri1AD0[2] = inttyp[Tri2->prot[2]]->ORI[2];
			cooTri2AD0[0] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3];
			cooTri2AD0[1] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3+1];
			cooTri2AD0[2] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3+2];
		   }
		   iset = 1;
		} else {
		   if (iset == 1) {
		   	if (j == 0) {
			   cooTri1AD1[0] = inttyp[Tri2->prot[0]]->ORI[0];
			   cooTri1AD1[1] = inttyp[Tri2->prot[0]]->ORI[1];
			   cooTri1AD1[2] = inttyp[Tri2->prot[0]]->ORI[2];
			   cooTri2AD1[0] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3];
			   cooTri2AD1[1] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3+1];
			   cooTri2AD1[2] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3+2];
		   	} else if (j == 1) {
			   cooTri1AD1[0] = inttyp[Tri2->prot[1]]->ORI[0];
			   cooTri1AD1[1] = inttyp[Tri2->prot[1]]->ORI[1];
			   cooTri1AD1[2] = inttyp[Tri2->prot[1]]->ORI[2];
			   cooTri2AD1[0] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3];
			   cooTri2AD1[1] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3+1];
			   cooTri2AD1[2] = coo[ligtyp[Tri2->lig[1]]->atom[0]*3+2];
		   	} else if (j == 2) {
			   cooTri1AD1[0] = inttyp[Tri2->prot[2]]->ORI[0];
			   cooTri1AD1[1] = inttyp[Tri2->prot[2]]->ORI[1];
			   cooTri1AD1[2] = inttyp[Tri2->prot[2]]->ORI[2];
			   cooTri2AD1[0] = coo[ligtyp[Tri2->lig[0]]->atom[0]*3];
			   cooTri2AD1[0] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3];
			   cooTri2AD1[1] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3+1];
			   cooTri2AD1[2] = coo[ligtyp[Tri2->lig[2]]->atom[0]*3+2];
		   	}
			iset = 2;
		   }
		}
	} else {
		type[j] = 0;
	}
	typtot = typtot + type[j];
   }

   if (typtot == 2) {
	spec = 1;
	if (!HAS_SPEC) HAS_SPEC = 1;
   }

   if (spec) {
	for (j = 0; j<3; j++ ) {
	   Cen[j] = (cooTri1AD0[j] + cooTri1AD1[j])/2.0;
	   Tri2->Cen[j] = (cooTri2AD0[j] + cooTri2AD1[j])/2.0;
	}
	for (j = 0; j<3; j++ ) {
	   t[j] = (double) (Cen[j] - Tri2->Cen[j]);
	   Tri2->t[j] = t[j];
	}
	Tri2->spec = 1;
   }

}

void Trans_Tri(Tri1,Tri2,opt)
TRISTRU *Tri1;
TRISTRU *Tri2;
int opt;
{
   int i,j,k,l,spec,type[3],typtot,iset,fnd;
   float v1[3],v2[3],v3[3],V1[4],V2[3],V3[3];
   float x,y,z,pt[3],pl,COSA,SINA,cosa,sina,csa,ca,sa,tang,atang,val;
   float cooTri1AD0[3],cooTri1AD1[3];
   float cooTri2AD0[3],cooTri2AD1[3];
   float z1[3],z2[3];
   double R1[4][4],R2[4][4],t[3];

   val = 180.0 / PI;

   spec = 0; type[0] = -1; type[1] = -1; type[2] = -1; typtot = 0;
   iset = -1;

/* Tri1 is original, Tri2 to be transformed Tri1 */

/* check for 2x H_DON/H_ACC + 1 != H_DON/H_ACC */

   for (j = 0; j<3; j++ ) {
	if (ligtyp[Tri1->lig[j]]->type == H_ACC ||
		ligtyp[Tri1->lig[j]]->type == H_DON) {
		type[j] = 1;
		if (iset == -1) {
		   if (j == 0) {
			cooTri1AD0[0] = Tri1->p1[0];
			cooTri1AD0[1] = Tri1->p1[1];
			cooTri1AD0[2] = Tri1->p1[2];
			cooTri2AD0[0] = Tri2->p1[0];
			cooTri2AD0[1] = Tri2->p1[1];
			cooTri2AD0[2] = Tri2->p1[2];
		   } else if (j == 1) {
			cooTri1AD0[0] = Tri1->p2[0];
			cooTri1AD0[1] = Tri1->p2[1];
			cooTri1AD0[2] = Tri1->p2[2];
			cooTri2AD0[0] = Tri2->p2[0];
			cooTri2AD0[1] = Tri2->p2[1];
			cooTri2AD0[2] = Tri2->p2[2];
		   } else if (j == 2) {
			cooTri1AD0[0] = Tri1->p3[0];
			cooTri1AD0[1] = Tri1->p3[1];
			cooTri1AD0[2] = Tri1->p3[2];
			cooTri2AD0[0] = Tri2->p3[0];
			cooTri2AD0[1] = Tri2->p3[1];
			cooTri2AD0[2] = Tri2->p3[2];
		   }
		   iset = 1;
		} else {
		   if (iset == 1) {
		   	if (j == 0) {
			   cooTri1AD1[0] = Tri1->p1[0];
			   cooTri1AD1[1] = Tri1->p1[1];
			   cooTri1AD1[2] = Tri1->p1[2];
			   cooTri2AD1[0] = Tri2->p1[0];
			   cooTri2AD1[1] = Tri2->p1[1];
			   cooTri2AD1[2] = Tri2->p1[2];
		   	} else if (j == 1) {
			   cooTri1AD1[0] = Tri1->p2[0];
			   cooTri1AD1[1] = Tri1->p2[1];
			   cooTri1AD1[2] = Tri1->p2[2];
			   cooTri2AD1[0] = Tri2->p2[0];
			   cooTri2AD1[1] = Tri2->p2[1];
			   cooTri2AD1[2] = Tri2->p2[2];
		   	} else if (j == 2) {
			   cooTri1AD1[0] = Tri1->p3[0];
			   cooTri1AD1[1] = Tri1->p3[1];
			   cooTri1AD1[2] = Tri1->p3[2];
			   cooTri2AD1[0] = Tri2->p3[0];
			   cooTri2AD1[1] = Tri2->p3[1];
			   cooTri2AD1[2] = Tri2->p3[2];
		   	}
			iset = 2;
		   }
		}
	} else {
		type[j] = 0;
	}
	typtot = typtot + type[j];
   }

   if (typtot == 2) {
	spec = 1;
	if (!HAS_SPEC) HAS_SPEC = 1;
   }

   if (spec) {

/* Tri1 is original, Tri2 to be transformed Tri1 */

	for (j = 0; j<3; j++ ) {
	   Tri1->Cen[j] = (cooTri1AD0[j] + cooTri1AD1[j])/2.0;
	   Tri2->Cen[j] = (cooTri2AD0[j] + cooTri2AD1[j])/2.0;
	}

	for (j = 0; j<3; j++ ) {
	   t[j] = (double) (Tri1->Cen[j] - Tri2->Cen[j]);
	   Tri2->t[j] = t[j];
	}

	Tri2->spec = 1;
   }

   for (j = 0; j<3; j++ ) {
	t[j] = (double) (Tri1->Cen[j] - Tri2->Cen[j]);
	if (spec) {
	   v3[j] = cooTri1AD0[j] - Tri1->Cen[j];
	   V1[j] = cooTri2AD0[j] - Tri2->Cen[j];
	} else {
	   v3[j] = Tri1->p1[j] - Tri1->Cen[j];
	   V1[j] = Tri2->p1[j] - Tri2->Cen[j];
	}
	V2[j] = Tri2->Out[j];
	Tri2->Cen[j] = Tri2->Cen[j] + (float) t[j];
	Tri2->p1c[j] = Tri2->p1[j] + t[j];
	Tri2->p2c[j] = Tri2->p2[j] + t[j];
	Tri2->p3c[j] = Tri2->p3[j] + t[j];
	Tri2->p1[j] = Tri1->p1c[j];
	Tri2->p2[j] = Tri1->p2c[j];
	Tri2->p3[j] = Tri1->p3c[j];
	Tri2->P1[j] = Tri1->p1[j];
	Tri2->P2[j] = Tri1->p2[j];
	Tri2->P3[j] = Tri1->p3[j];
	Tri2->t[j] = t[j];
	Tri2->CenO[j] = Tri1->Cen[j];
	Tri2->OutOrg[j] = Tri1->Out[j];
	if (!opt) {
	   Tri2->prot[j] = Tri1->prot[j];
	   Tri2->lig[j] = Tri1->lig[j];
	   Tri2->ohlig[j] = Tri1->ohlig[j];
	}
   }

   if (spec && Tri2->oneline) {

	for (j = 0; j<3; j++ ) {
	   v1[j] = cooTri1AD1[j] - cooTri1AD0[j];
	   v2[j] = cooTri2AD1[j] - cooTri2AD0[j];
	}

	vecnrm(v1);
	vecnrm(v2);

// V3 perpendicular to v1 and v2, this should be rotation axis, V3 ??

	cross(v1,v2,V3);
	vecnrm(V3);

// v3 perpendicular to v1 and V3

	cross(v1,V3,v3);
	vecnrm(v3);

	IMPRD(v1,v2,&cosa,1);
 	IMPRD(v2,v3,&sina,1);

        tang = sina / cosa;
        atang = atan(tang) * val;

 	sina = sin(tang);
	cosa = cos(tang);

	Frst_Rot(Tri1->Cen,V3,sina,cosa,R1);

	xyzROT4(R1,Tri2->p1c);
	xyzROT4(R1,Tri2->p2c);
	xyzROT4(R1,Tri2->p3c);

	for (j = 0; j<3; j++ ) {
	   Tri2->p1[j] = Tri2->p1c[j];
	   Tri2->p2[j] = Tri2->p2c[j];
	   Tri2->p3[j] = Tri2->p3c[j];
	}

	for (i=0; i<4; i++) 
	   for (j=0; j<4; j++) Tri2->R1[i][j] = R1[i][j];

	return;
   }

   vecnrm(Tri2->Out);
   vecnrm(Tri1->Out);

   cross(Tri2->Out,Tri1->Out,v1);
   cross(Tri1->Out,Tri2->Out,v1);
   cross(Tri1->Out,v1,v2);
   
   vecnrm(v1);
   vecnrm(v2);
   
   IMPRD(Tri2->Out,Tri1->Out,&cosa,1);
   IMPRD(Tri2->Out,v2,&sina,1);

   Frst_Rot(Tri1->Cen,v1,sina,cosa,R1);

   vecnrm(V1);
   vecnrm(V2);
   
   xyzROT3(R1,V1);
   xyzROT3(R1,V2);

   xyzROT4(R1,Tri2->p1c);
   xyzROT4(R1,Tri2->p2c);
   xyzROT4(R1,Tri2->p3c);

   for (j = 0; j<3; j++ ) {
	Tri2->p1[j] = Tri2->p1c[j];
	Tri2->p2[j] = Tri2->p2c[j];
	Tri2->p3[j] = Tri2->p3c[j];
   }

   for (j = 0; j<3; j++ ) {
	Tri2->OutO[j] = V2[j];
   }


   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri2->R1[i][j] = R1[i][j];

   cross(Tri1->Out,v3,v2);

/* orthonormal basis Tri2.out=z,v2=x,v3=y */

   vecnrm(v2);
   vecnrm(v3);
   vecnrm(Tri1->Out);
   vecnrm(V1);
   cross(V2,V1,V3);

   IMPRD(v3,V1,&COSA,1);
   IMPRD(v3,V3,&SINA,1);

   Frst_Rot(Tri2->Cen,V2,SINA,COSA,R2);

   xyzROT4(R2,Tri2->p1c);
   xyzROT4(R2,Tri2->p2c);
   xyzROT4(R2,Tri2->p3c);

   for (j = 0; j<3; j++ ) {
	Tri2->p1[j] = Tri2->p1c[j];
	Tri2->p2[j] = Tri2->p2c[j];
	Tri2->p3[j] = Tri2->p3c[j];
   }

   for (j = 0; j<3; j++ ) {
	Tri2->p1[j] = Tri2->p1c[j];
	Tri2->p2[j] = Tri2->p2c[j];
	Tri2->p3[j] = Tri2->p3c[j];
   }

   for (i=0; i<4; i++) 
     for (j=0; j<4; j++) Tri2->R2[i][j] = R2[i][j];

   if (Tri2->spec == 1) {
	R3calc(Tri1,Tri2,cooTri1AD0,cooTri2AD0);
   }
}

double Dind(int ind1, int ind2, int pnt1, int pnt2)
{
   int l;
   double ddd,tt;

   ddd = 0.0;
   for (l=0; l < 3; l++) {
	tt = inttyp[ind1]->points[pnt1*3+l] -
	     inttyp[ind2]->points[pnt2*3+l];
	ddd = ddd + tt*tt;
   }
   ddd = sqrt(ddd)*TOANG;

   return(ddd);
}

int Triangle_Same_Previous(Tri1,Tri2)
TRISTRU *Tri1;
TRISTRU *Tri2;
{
   int i;


/* Tri->d12,d13,d23 angs
   Tri->p1,p2,p3 au */

   if (Tri1 == NULL || Tri2 == NULL) return 0;

   if (Tri1->prot[0] != Tri2->prot[0] || Tri1->prot[1] != Tri2->prot[1] || 
	Tri1->prot[2] != Tri2->prot[2]) return 0;

   if (ABS(Tri1->d12 - Tri2->d12) < 0.001 && ABS(Tri1->d13 - Tri2->d13) < 0.001 && ABS(Tri1->d23 - Tri2->d23) < 0.001) {

	for (i=0; i < 3; i++) {
	    if (ABS(Tri1->p1c[i] - Tri2->p1c[i]) > 0.001) return 0;
	    if (ABS(Tri1->p2c[i] - Tri2->p2c[i]) > 0.001) return 0;
	    if (ABS(Tri1->p3c[i] - Tri2->p3c[i]) > 0.001) return 0;
	}
	return 1;
   } else {
	return 0;
   }
}

#define MAXSOLLIGTRI 20

void Find_Triangle_Match(Tri,idxs,dophr)
TRISTRU Tri;
int idxs;
int dophr;
{
   int grp[3],ogrp[3],i,j,k,l,ii,kk,idd,iee,n,m;
   int ind1,ind2,pnt1,pnt2,jind,jpnt,yesh,small,ophr;
   int AddTri,oo,idmin,idmax,iemin,iemax,iii,kkk,N,d100,maxs;
   float dd,ee,tt,ddd,ddt,eet,dckc,sum;
   GRPSTRU *grp_p01, *grp_p12;
   CROSSSTRU *xrsii, *xrskk;
   TRISTRU TriA;

   itry = 1;
   d100 = (int) dckcoff*dckcoff;
   dckc = (float) dckcoff;

   if (Tri.d12 > dckc || Tri.d13 > dckc || Tri.d23 > dckc) return;

   maxs = MAXSOLLIGTRI;
   small = 0;
   sum = Tri.d12 + Tri.d13 + Tri.d23;
   if ( sum < 10.0) {
	maxs = 150;
	small = 1;
   }

   TriA = Tri;

/* convert specific group to general groups: eg H_ACC to H_ACC_GROUP */

   ogrp[0] = Find_Group(Tri.grp[0]);
   ogrp[1] = Find_Group(Tri.grp[1]);
   ogrp[2] = Find_Group(Tri.grp[2]);

/* convert general groups to general matching groups */

   if (!dophr) {
	grp[0] = Find_Matching_Group(ogrp[0]);
	grp[1] = Find_Matching_Group(ogrp[1]);
	grp[2] = Find_Matching_Group(ogrp[2]);
   } else {
	ophr = Find_Matching_Group(ogrp[0]);
	if (ophr == 2) grp[0] = 3;
        else grp[0] = ophr;
	ophr = Find_Matching_Group(ogrp[1]);
	if (ophr == 2) grp[1] = 3;
        else grp[1] = ophr;
	ophr = Find_Matching_Group(ogrp[2]);
	if (ophr == 2) grp[2] = 3;
        else grp[2] = ophr;
   }

   grp_p01 = &XGRP[grp[0]][grp[1]];
   if (grp_p01->n == 0) grp_p01 = &XGRP[grp[1]][grp[0]];
   grp_p12 = &XGRP[grp[1]][grp[2]];
   if (grp_p12->n == 0) grp_p12 = &XGRP[grp[2]][grp[1]];

   if (grp_p01->n == 0) return;
   if (grp_p12->n == 0) return;

   if (grp_p01->XDist == NULL)  return;
   if (grp_p01->XHash == NULL)  return;
   if (grp_p12->XDist == NULL)  return;
   if (grp_p12->XHash == NULL)  return;

   dd = ABS(Tri.d12 - DCKdev); 
   if (dd > dckc) {
	idmin = d100;
   } else if (dd < DCKCMIN) {
	idmin = 1;
   } else {
	idmin = (int) rndf(dd*10.0);
	if (idmin > d100) return;
   }

   dd = ABS(Tri.d12 + DCKdev); 
   if (dd > dckc) {
	idmax = d100;
   } else if (dd < DCKCMIN) {
	idmax = 1;
   } else {
	idmax = (int) rndf(dd*10.0);
	if (idmax > d100) idmax = d100;
   }

   ee = ABS(Tri.d23 - DCKdev); 
   if (ee > dckc) {
	iemin = d100;
   } else if (ee < DCKCMIN) {
	iemin = 1;
   } else {
	iemin = (int) rndf(ee*10.0);
	if (iemin > d100) return;
   }

   ee = ABS(Tri.d23 + DCKdev);
   if (ee > dckc) {
	iemax = d100;
   } else if (ee < DCKCMIN) {
	iemax = 1;
   } else {
	iemax = (int) rndf(ee*10.0);
	if (iemax > d100) iemax = d100;
   }

   for (idd = idmin; idd < idmax+1; idd++ ) {
     N = 0;
     for (iee = iemin; iee < iemax+1; iee++ ) {

       n   = grp_p01->XHash[idd].n;
       ii  = grp_p01->XHash[idd].ind;

       if (ii+n >= grp_p01->n) break;

       m   = grp_p12->XHash[iee].n;
       kk  = grp_p12->XHash[iee].ind;

       if (kk+m >= grp_p12->n) break;

       for (i = 0; i < n; i++ ) {

	iii = ii + i;
	if (iii >= grp_p01->n || ii < 0) break;
	xrsii = &grp_p01->XDist[iii];

	ddt  = xrsii->d;

	for (k = 0; k < m; k++ ) {
	   kkk = kk + k;
	   if (kkk >= grp_p12->n || kk < 0) break;
	   xrskk = &grp_p12->XDist[kkk];

	   eet  = xrskk->d;

	   yesh = -1;

	   if (xrsii->grp2 == grp[1]) {

		if (xrskk->grp2 == grp[1]) {
		   if (xrsii->ind2 == xrskk->ind2 && 
		       xrsii->pnt2 == xrskk->pnt2) yesh = 1;

		} else if (xrskk->grp1 == grp[1]) {
		   if (xrsii->ind2 == xrskk->ind1 && 
		       xrsii->pnt2 == xrskk->pnt1) yesh = 2;
		}

	   } else if (xrsii->grp1 == grp[1]) {

		if (xrskk->grp1 == grp[1]) {
		   if (xrsii->ind1 == xrskk->ind1 && 
		       xrsii->pnt1 == xrskk->pnt1) yesh = 3;
		} else if (xrskk->grp2 == grp[1]) {
		   if (xrsii->ind1 == xrskk->ind2 && 
		       xrsii->pnt1 == xrskk->pnt2) yesh = 4;
		}
	   }

	   if (yesh != -1) {


		switch (yesh) {
		case 1:

		   ind1 = xrsii->ind1;
		   ind2 = xrskk->ind1;
		   pnt1 = xrsii->pnt1;
		   pnt2 = xrskk->pnt1;
		   jind = xrsii->ind2;
		   jpnt = xrsii->pnt2;
		   break;

		case 2:

		   ind1 = xrsii->ind1;
		   ind2 = xrskk->ind2;
		   pnt1 = xrsii->pnt1;
		   pnt2 = xrskk->pnt2;
		   jind = xrsii->ind2;
		   jpnt = xrsii->pnt2;
		   break;

		case 3:

		   ind1 = xrsii->ind2;
		   ind2 = xrskk->ind2;
		   pnt1 = xrsii->pnt2;
		   pnt2 = xrskk->pnt2;
		   jind = xrsii->ind1;
		   jpnt = xrsii->pnt1;
		   break;

		case 4:

		   ind1 = xrsii->ind2;
		   ind2 = xrskk->ind1;
		   pnt1 = xrsii->pnt2;
		   pnt2 = xrskk->pnt1;
		   jind = xrsii->ind1;
		   jpnt = xrsii->pnt1;
		   break;

		default:
		   break;
		}

		ddd = 0.0;
		if (inttyp[ind1] != NULL && inttyp[ind2] != NULL) {
		   for (l=0; l < 3; l++) {
			tt = inttyp[ind1]->points[pnt1*3+l] -
		        	inttyp[ind2]->points[pnt2*3+l];
		   	ddd = ddd + tt*tt;
		   }
		   ddd = sqrt(ddd)*TOANG;
		}

		if ((ABS(Tri.d13 - ddd) < DCKdev) &&
		    (ABS(Tri.d12 - ddt) < DCKdev) &&
		    (ABS(Tri.d23 - eet) < DCKdev)) {

			ntris++; N++;
			if (ntris >= MAXTRI) {
			   ntris = MAXTRI - 1;
			   return;
/*			fprintf(stderr,"ntris exceeded MAXTRI\n");*/
			} else {

			   if (N >= maxs) goto IDD;

	   		   TriAll(&TriArr[ntris]);
			   TriArr[ntris]->coo = NULL;
			   TriArr[ntris]->small = small;

			   for (l=0; l < 3; l++) {
				TriArr[ntris]->p1[l] = Tri.p1[l];
				TriArr[ntris]->p2[l] = Tri.p2[l];
				TriArr[ntris]->p3[l] = Tri.p3[l];
				TriArr[ntris]->grp[l] = Tri.grp[l];
				TriArr[ntris]->lig[l] = Tri.lig[l];
			   }

			   Calc_Centroid(TriArr[ntris]);

			   if (inttyp[ind1] != NULL && inttyp[jind] != NULL && inttyp[ind2] != NULL) {
			      for (l=0; l < 3; l++) {
				TriA.p1[l] = 
				   inttyp[ind1]->points[pnt1*3+l];
				TriA.p2[l] = 
				   inttyp[jind]->points[jpnt*3+l];
				TriA.p3[l] = 
				   inttyp[ind2]->points[pnt2*3+l];
				TriA.grp[l] = grp[l];
			      }
			   } else {
			      return;
			   }

			   TriA.prot[0] = ind1;
			   TriA.prot[1] = jind;
			   TriA.prot[2] = ind2;

			   TriArr[ntris]->prot[0] = ind1;
			   TriArr[ntris]->prot[1] = jind;
			   TriArr[ntris]->prot[2] = ind2;

			   Calc_Centroid(&TriA);

			   AddTri = 1;
 			   if (ntris > 1) {
 			      if (Triangle_Same_Previous(
				    TriArr[ntris],TriArr[ntris-1])) AddTri = 0;
			   }

			   if (ind1 == ind2) AddTri = 0;

			   if (AddTri) {

// TriA contains protein triangle. TriArr[ntris] contains ligand triangle

				TriArr[ntris]->conf = Tri.conf;
				TriArr[ntris]->nconf = Tri.nconf;
				TriArr[ntris]->oneline = Tri.oneline;
				Trans_Tri(&TriA,TriArr[ntris],0);

				if (TriArr[ntris]->conf == -1) {
				   TriArr[ntris]->frag = Tri.frag;
				} else {
				   TriArr[ntris]->frag = -1;
				   TriArr[ntris]->frags[0] = Tri.frags[0];
				   TriArr[ntris]->frags[1] = Tri.frags[1];
				   TriArr[ntris]->frags[2] = Tri.frags[2];
				}
				TriArr[ntris]->triS = idxs;

			   } else {
			 	TriCooSafeFree(ntris);
				ntris--;
			   }
			}

		}
	   }
	} /* end for (k = 0; k < m; k++ ) */
       } /* end for (i = 0; i < n; i++ ) */

     }
IDD:
     i = 0;
   }
}

float CalInt(ind1,ind2,lpoints,t,R1,R2,OutO,OutOrg,deb)
int ind1;
int ind2;
double *lpoints;
double t[3];
double R1[4][4];
double R2[4][4];
float OutO[3];
float OutOrg[3];
int deb;
{
    int i,j,l,ipr;
    float e12,ddev,adev1,adev2,dd,aqmin,aq,at,todeg;
    float fq1,fq2,fd1,fa1,fa2;
    float O[3],T[3];
    double ctmp[3],v1[3],v2[3],cosa;
   
    ipr = 0;

//  Because the translation and rotations R1 and R2 only work on
//  the original ORI[3] and since we apply the operations allready
//  on the TriArr[]->ORI[3], we needed a copy of the original ORI[]
//  This only goes for the ligand ORI[3], NOT the protein ORI[3]

    for (l=0; l < 3; l++) O[l] = t[l] + ligtyp[ind2]->ORI[l];
    xyzROT4(R1,O);
    xyzROT4(R2,O);

    todeg = 45.0e0/atan(1.0e0);

    e12 = inttyp[ind1]->area.ene + ligtyp[ind2]->area.ene;

    fq1 = 1.0;

    if (inttyp[ind1]->q0*ligtyp[ind2]->q0 < inttyp[ind1]->area.chgsc[1])
	fq1 = inttyp[ind1]->area.chgsc[0];

    fq2 = 1.0;

    if (inttyp[ind1]->q0*ligtyp[ind2]->q0 < ligtyp[ind2]->area.chgsc[1])
	fq2 = ligtyp[ind2]->area.chgsc[0];

    fd1 = 1.0;

    ddev = 0.0;

    for (i = 0; i < 3; i++ ) {
	dd = (inttyp[ind1]->ORI[i] - O[i]);
	ddev +=  dd*dd;
    }

    ddev = sqrt(ddev);
    ddev = ddev*toangs;

    ddev = ddev - 0.5*(inttyp[ind1]->area.radius + ligtyp[ind2]->area.radius);
    ddev = ABS(ddev);

    if (ddev <= inttyp[ind1]->area.dissc[0]) {
	fd1 = 1.0;
    } else if (inttyp[ind1]->area.dissc[0] < ddev && 
	ddev < inttyp[ind1]->area.dissc[1]) {
	fd1 = 1.0 - (ddev - inttyp[ind1]->area.dissc[0])/
		    (inttyp[ind1]->area.dissc[1]-inttyp[ind1]->area.dissc[0]);
    } else {
	fd1 = 0.0;
	return 0.0;
    }

    if (inttyp[ind1]->area.angsc[0] == 0 && 
	inttyp[ind1]->area.angsc[1] == 360.0) {

	fa1 = 1.0;

    } else {

	
	adev1 = 0.0;
	aqmin = 10000.0;

	for (i = 0; i < inttyp[ind1]->npts; i++ ) {
	   aq = 0.0;
	   for (j = 0; j < 3; j++ ) {
		at = inttyp[ind1]->points[i*3+j] - O[j];
		aq = aq + at*at;
	   }
	   if (aq < aqmin) {
		aqmin = aq;
		for (j = 0; j < 3; j++ ) 
		   ctmp[j] = inttyp[ind1]->points[i*3+j];
	   }
	}

	for (j = 0; j < 3; j++ ) {
	   v1[j] = O[j] - inttyp[ind1]->ORI[j];
	   v2[j] = ctmp[j] - inttyp[ind1]->ORI[j];
	}
    
	dinprod(v1,v2,&cosa);

	if (fabs(cosa) == 1.0) {
           adev1 = 0.0;
	   if (cosa < 0) adev1 = 180.0;
	} else {
           adev1 = (float) acos(cosa)*todeg;
	}
    
	fa1 = 1.0;

	if (adev1 <= inttyp[ind1]->area.angsc[0]) {
	   fa1 = 1.0;
	} else if (inttyp[ind1]->area.angsc[0] < adev1 && 
		   adev1 < inttyp[ind1]->area.angsc[1]) {
	   fa1 = 1.0 - (adev1 - inttyp[ind1]->area.angsc[0])/
		    (inttyp[ind1]->area.angsc[1]-inttyp[ind1]->area.angsc[0]);
	} else {
	   fa1 = 0.0;
	   return 0.0;
	}
    }


    if (ligtyp[ind2]->area.angsc[0] == 0 && 
	ligtyp[ind2]->area.angsc[1] == 360.0) {

	fa2 = 1.0;

    } else {

	adev2 = 0.0;
	aqmin = 10000.0;

	for (i = 0; i < ligtyp[ind2]->npts; i++ ) {
	   aq = 0.0;
	   for (j = 0; j < 3; j++ ) T[j] = t[j] + lpoints[i*3+j];
	   xyzROT4(R1,T);
	   xyzROT4(R2,T);
	   for (j = 0; j < 3; j++ ) {
		at = T[j] - inttyp[ind1]->ORI[j];
		aq = aq + at*at;
	   }
	   if (aq < aqmin) {
		aqmin = aq;
		for (j = 0; j < 3; j++ ) ctmp[j] = T[j];
	   }
	}

	for (j = 0; j < 3; j++ ) {
	   v1[j] = inttyp[ind1]->ORI[j] - O[j];
	   v2[j] = ctmp[j] - O[j];
	}
    
	dinprod(v1,v2,&cosa);

	if (fabs(cosa) == 1.0) {
           adev2 = 0.0;
	   if (cosa < 0) adev2 = 180.0;
	} else {
           adev2 = (float) acos(cosa)*todeg;
	}
    
	fa2 = 1.0;

	if (adev2 <= ligtyp[ind2]->area.angsc[0]) {
	   fa2 = 1.0;
	} else if (ligtyp[ind2]->area.angsc[0] < adev2 && 
		   adev2 < ligtyp[ind2]->area.angsc[1]) {
	   fa2 = 1.0 - (adev2 - ligtyp[ind2]->area.angsc[0])/
		    (ligtyp[ind2]->area.angsc[1]-ligtyp[ind2]->area.angsc[0]);
	} else {
	   fa2 = 0.0;
	   return 0.0;
	}
    }

if (fq1 < 0.0 || fq2 < 0.0 || fd1 < 0.0 || fa1 < 0.0 || fa2 < 0.0) 
	fprintf(stderr,"CalInt: fq1 %.3f fq2 %.3f fd1 %.3f fa1 %.3f fa2 %.3f\n",fq1,fq2,fd1,fa1,fa2);

    e12 = e12*fq1*fq2*fd1*fa1*fa2;
    return e12;
}

float CalInt_Spec(ind1,ind2,lpoints,t,R1,R2,OutO,OutOrg,spec,deb)
int ind1;
int ind2;
double *lpoints;
double t[3];
double R1[4][4];
double R2[4][4];
float OutO[3];
float OutOrg[3];
int spec;
int deb;
{
    int i,j,l,ipr;
    float e12,ddev,adev1,adev2,dd,aqmin,aq,at,todeg;
    float fq1,fq2,fd1,fa1,fa2;
    float O[3],T[3];
    double ctmp[3],v1[3],v2[3],cosa;
   
    ipr = 0;

    for (l=0; l < 3; l++) O[l] = t[l] + ligtyp[ind2]->ORI[l];
    xyzROT4(R1,O);
    if (!spec) xyzROT4(R2,O);

    todeg = 45.0e0/atan(1.0e0);

    e12 = inttyp[ind1]->area.ene + ligtyp[ind2]->area.ene;

    fq1 = 1.0;

    if (inttyp[ind1]->q0*ligtyp[ind2]->q0 < inttyp[ind1]->area.chgsc[1])
	fq1 = inttyp[ind1]->area.chgsc[0];

    fq2 = 1.0;

    if (inttyp[ind1]->q0*ligtyp[ind2]->q0 < ligtyp[ind2]->area.chgsc[1])
	fq2 = ligtyp[ind2]->area.chgsc[0];

    fd1 = 1.0;

    ddev = 0.0;

    for (i = 0; i < 3; i++ ) {
	dd = (inttyp[ind1]->ORI[i] - O[i]);
	ddev +=  dd*dd;
    }

    ddev = sqrt(ddev);
    ddev = ddev*toangs;

    ddev = ddev - 0.5*(inttyp[ind1]->area.radius + ligtyp[ind2]->area.radius);
    ddev = ABS(ddev);

    if (ddev <= inttyp[ind1]->area.dissc[0]) {
	fd1 = 1.0;
    } else if (inttyp[ind1]->area.dissc[0] < ddev && 
	ddev < inttyp[ind1]->area.dissc[1]) {
	fd1 = 1.0 - (ddev - inttyp[ind1]->area.dissc[0])/
		    (inttyp[ind1]->area.dissc[1]-inttyp[ind1]->area.dissc[0]);
    } else {
	fd1 = 0.0;
	return 0.0;
    }

    if (inttyp[ind1]->area.angsc[0] == 0 && 
	inttyp[ind1]->area.angsc[1] == 360.0) {

	fa1 = 1.0;

    } else {

	
	adev1 = 0.0;
	aqmin = 10000.0;

	for (i = 0; i < inttyp[ind1]->npts; i++ ) {
	   aq = 0.0;
	   for (j = 0; j < 3; j++ ) {
		at = inttyp[ind1]->points[i*3+j] - O[j];
		aq = aq + at*at;
	   }
	   if (aq < aqmin) {
		aqmin = aq;
		for (j = 0; j < 3; j++ ) 
		   ctmp[j] = inttyp[ind1]->points[i*3+j];
	   }
	}

	for (j = 0; j < 3; j++ ) {
	   v1[j] = O[j] - inttyp[ind1]->ORI[j];
	   v2[j] = ctmp[j] - inttyp[ind1]->ORI[j];
	}
    
	dinprod(v1,v2,&cosa);

	if (fabs(cosa) == 1.0) {
           adev1 = 0.0;
	   if (cosa < 0) adev1 = 180.0;
	} else {
           adev1 = (float) acos(cosa)*todeg;
	}
    
	fa1 = 1.0;

	if (adev1 <= inttyp[ind1]->area.angsc[0]) {
	   fa1 = 1.0;
	} else if (inttyp[ind1]->area.angsc[0] < adev1 && 
		   adev1 < inttyp[ind1]->area.angsc[1]) {
	   fa1 = 1.0 - (adev1 - inttyp[ind1]->area.angsc[0])/
		    (inttyp[ind1]->area.angsc[1]-inttyp[ind1]->area.angsc[0]);
	} else {
	   fa1 = 0.0;
	   return 0.0;
	}
    }


    if (ligtyp[ind2]->area.angsc[0] == 0 && 
	ligtyp[ind2]->area.angsc[1] == 360.0) {

	fa2 = 1.0;

    } else {

	adev2 = 0.0;
	aqmin = 10000.0;

	for (i = 0; i < ligtyp[ind2]->npts; i++ ) {
	   aq = 0.0;
	   for (j = 0; j < 3; j++ ) T[j] = t[j] + lpoints[i*3+j];
	   xyzROT4(R1,T);
	   xyzROT4(R2,T);
	   for (j = 0; j < 3; j++ ) {
		at = T[j] - inttyp[ind1]->ORI[j];
		aq = aq + at*at;
	   }
	   if (aq < aqmin) {
		aqmin = aq;
		for (j = 0; j < 3; j++ ) ctmp[j] = T[j];
	   }
	}

	for (j = 0; j < 3; j++ ) {
	   v1[j] = inttyp[ind1]->ORI[j] - O[j];
	   v2[j] = ctmp[j] - O[j];
	}
    
	dinprod(v1,v2,&cosa);

	if (fabs(cosa) == 1.0) {
           adev2 = 0.0;
	   if (cosa < 0) adev2 = 180.0;
	} else {
           adev2 = (float) acos(cosa)*todeg;
	}
    
	fa2 = 1.0;

	if (adev2 <= ligtyp[ind2]->area.angsc[0]) {
	   fa2 = 1.0;
	} else if (ligtyp[ind2]->area.angsc[0] < adev2 && 
		   adev2 < ligtyp[ind2]->area.angsc[1]) {
	   fa2 = 1.0 - (adev2 - ligtyp[ind2]->area.angsc[0])/
		    (ligtyp[ind2]->area.angsc[1]-ligtyp[ind2]->area.angsc[0]);
	} else {
	   fa2 = 0.0;
	   return 0.0;
	}
    }

if (e12 > 0.0) fprintf(stderr,"CalInt: e12 %.3f\n",e12);
if (fq1 < 0.0 || fq2 < 0.0 || fd1 < 0.0 || fa1 < 0.0 || fa2 < 0.0) 
	fprintf(stderr,"CalInt: fq1 %.3f fq2 %.3f fd1 %.3f fa1 %.3f fa2 %.3f\n",fq1,fq2,fd1,fa1,fa2);

    e12 = e12*fq1*fq2*fd1*fa1*fa2;
    return e12;
}

void Tris_NoLink()
{
    int i,j,n,ihacc1,ihacc2,ihdon1,ihdon2;

    for (i=0; i < ntriS; i++) {
	if ((TriS[i].grp[0] == H_ACC || TriS[i].grp[1] == H_ACC || 
		TriS[i].grp[2] == H_ACC) ||
	    (TriS[i].grp[0] == H_DON || TriS[i].grp[1] == H_DON ||
		TriS[i].grp[2] == H_DON)) {

		   ihacc1 = -1; ihdon1 = -1;
		   ihacc2 = -1; ihdon2 = -1;
		   for (j=0; j < 3; j++) {
			if (TriS[i].grp[j] == H_ACC) {
			   if (ihacc1 == -1) {
				ihacc1 = j;
			   } else if (ihacc2 == -1) {
				ihacc2 = j;
			   }
			}
		   }
		   for (j=0; j < 3; j++) {
			if (TriS[i].grp[j] == H_DON) {
			   if (ihdon1 == -1) {
				ihdon1 = j;
			   } else if (ihdon2 == -1) {
				ihdon2 = j;
			   }
			}
		   }
		   if ((ihacc1 != -1 || ihacc2 != -1) && 
		       (ihdon1 != -1 || ihdon2 != -1)) {

		     if (ihdon1 != -1 && ihacc1 != -1) {
			if (ligtyp[TriS[i].lig[ihdon1]]->link != -1 &&
			    ligtyp[TriS[i].lig[ihacc1]]->link != -1) {
			   if (ligtyp[TriS[i].lig[ihdon1]]->link == 
			       ligtyp[TriS[i].lig[ihacc1]]->link) {
				TriS[i].active = 0;
			   }
			}
		     }
		     if (ihdon1 != -1 && ihacc2 != -1) {
			if (ligtyp[TriS[i].lig[ihdon1]]->link != -1 &&
			    ligtyp[TriS[i].lig[ihacc2]]->link != -1) {
			   if (ligtyp[TriS[i].lig[ihdon1]]->link == 
			       ligtyp[TriS[i].lig[ihacc2]]->link) {
				TriS[i].active = 0;
			   }
			}
		     }
		     if (ihdon2 != -1 && ihacc1 != -1) {
			if (ligtyp[TriS[i].lig[ihdon2]]->link != -1 &&
			    ligtyp[TriS[i].lig[ihacc1]]->link != -1) {
			   if (ligtyp[TriS[i].lig[ihdon2]]->link == 
			       ligtyp[TriS[i].lig[ihacc1]]->link) {
				TriS[i].active = 0;
			   }
			}
		     }
		     if (ihdon2 != -1 && ihacc2 != -1) {
			if (ligtyp[TriS[i].lig[ihdon2]]->link != -1 &&
			    ligtyp[TriS[i].lig[ihacc2]]->link != -1) {
			   if (ligtyp[TriS[i].lig[ihdon2]]->link == 
			       ligtyp[TriS[i].lig[ihacc2]]->link) {
				TriS[i].active = 0;
			   }
			}
		     }
		   }
	}
    }

    n = 0;
    for (i=0; i < ntriS; i++) {
	if (TriS[i].active) {
	   TriS[n] = TriS[i];
	   n++;
	}
    }
    ntriS = n;

    if (debugdck) fprintf(stderr,"Tris_NoLink: ntris reduced %d \n",ntriS);
}

void Sub_Selection_Tris()
{
    int i,j,n,ispair,oh0,oh1,oh2;
// The purpose of this function is to make a subselection of triples in TriS[]
// that have at least one pair of acceptors or donors:
// acc-acc, acc-don or don-don
    n = 0;

    for (i=0; i < ntriS; i++) {
	ispair = 0;
	if ((TriS[i].grp[0] == H_ACC || TriS[i].grp[0] == H_DON)) ispair++;
	if ((TriS[i].grp[1] == H_ACC || TriS[i].grp[1] == H_DON)) ispair++;
	if ((TriS[i].grp[2] == H_ACC || TriS[i].grp[2] == H_DON)) ispair++;
	if (ispair < 2) {
	   TriS[i].active = 0;
	} else {
	   if (TriS[i].grp[0] == H_DON && TriS[i].grp[1] == H_DON) {
		if (ligtyp[TriS[i].lig[0]]->ohlig && 
		    ligtyp[TriS[i].lig[1]]->ohlig) {
		    oh0 = ABS(ligtyp[TriS[i].lig[0]]->ohsame);
		    oh1 = ABS(ligtyp[TriS[i].lig[1]]->ohsame);
		    if (oh0 == oh1) TriS[i].active = 0;
		}
	   } else if (TriS[i].grp[0] == H_DON && TriS[i].grp[2] == H_DON) {
		if (ligtyp[TriS[i].lig[0]]->ohlig && 
		    ligtyp[TriS[i].lig[2]]->ohlig) {
		    oh0 = ABS(ligtyp[TriS[i].lig[0]]->ohsame);
		    oh2 = ABS(ligtyp[TriS[i].lig[2]]->ohsame);
		    if (oh0 == oh2) TriS[i].active = 0;
		}
	   } else if (TriS[i].grp[1] == H_DON && TriS[i].grp[2] == H_DON) {
		if (ligtyp[TriS[i].lig[1]]->ohlig && 
		    ligtyp[TriS[i].lig[2]]->ohlig) {
		    oh1 = ABS(ligtyp[TriS[i].lig[1]]->ohsame);
		    oh2 = ABS(ligtyp[TriS[i].lig[2]]->ohsame);
		    if (oh1 == oh2) TriS[i].active = 0;
		}
	   } else {
		n++;
	   }
	}
    }

    n = 0;
    for (i=0; i < ntriS; i++) {
	if (TriS[i].active) {
	   TriS[n] = TriS[i];
	   n++;
	}
    }
    ntriS = n;

    fprintf(stderr,"Sub_Selection_Tris: ntris reduced %d \n",ntriS);
}

int Monitor_AccDon(n1,n2,p1,p2,npair,npairl)
int n1;
int n2;
int *p1;
int *p2;
int *npair;
int *npairl;
{

   int i,j,l,l1,l2,Conf;
   double r,tt,toangs2,DCKCOFF2,R2MIN;

   toangs2 = TOANG*TOANG;
   DCKCOFF2 = dckcoff*dckcoff;

   R2MIN = BIGD;


// acc - don combination

   *npair = 0; *npairl = 0;

   for (i=0; i < n1; i++) {

     for (j=0; j < n2; j++) {
	if ((ligtyp[p2[j]]->ohlig && ligtyp[p2[j]]->ohsame < 0) ||
	     !ligtyp[p2[j]]->ohlig) {

	   if (CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p2[j]]->ORI) &&
		ligtyp[p1[i]]->frag[0] == ligtyp[p2[j]]->frag[0]) {

	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p2[j]]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 < R2MIN && r*toangs2 > DCKCMIN*DCKCMIN) {
 		R2MIN = r*toangs2;
		*npair = *npair + 1;
		   if (ligtyp[p1[i]]->link != -1 && 
			ligtyp[p2[j]]->link != -1) {
		      if (ligtyp[p1[i]]->link != ligtyp[p2[j]]->link) {
			*npairl = *npairl + 1;
		      }
		   }

	      }

	   }
	}
     }
   }

// acc - acc combination

   for (i=0; i < n1; i++) {

     for (j=0; j < n1; j++) {

	if (i != j) {

	   if (CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p1[j]]->ORI) &&
		ligtyp[p1[i]]->frag[0] == ligtyp[p1[j]]->frag[0]) {

	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p1[j]]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 < R2MIN && r*toangs2 > DCKCMIN*DCKCMIN) {
 		R2MIN = r*toangs2;
		*npair = *npair + 1;
		*npairl = *npairl + 1;
	      }

	   }
	}
     }
   }

// don - don combination

   for (i=0; i < n2; i++) {

     for (j=0; j < n2; j++) {

	if (i != j) {

	 if (((ligtyp[p2[i]]->ohlig && ligtyp[p2[i]]->ohsame < 0) &&
	     (ligtyp[p2[j]]->ohlig && ligtyp[p2[j]]->ohsame < 0)) ||
	      !ligtyp[p2[j]]->ohlig || !ligtyp[p2[i]]->ohlig) {
	   if (CmpORI(ligtyp[p2[i]]->ORI,ligtyp[p2[j]]->ORI) &&
		ligtyp[p2[i]]->frag[0] == ligtyp[p2[j]]->frag[0]) {

	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[p2[i]]->ORI[l] - ligtyp[p2[j]]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 < R2MIN && r*toangs2 > DCKCMIN*DCKCMIN) {
 		R2MIN = r*toangs2;
		*npair = *npair + 1;
		*npairl = *npairl + 1;
	      }

	   }
	 }
	}
     }
   }

   if (R2MIN != BIGD) {
	if (R2MIN > DCKCOFF2) {
	   dckcoff = 15.0;
	   fprintf(stderr,"NEW DCKCOFF %.3f\n",dckcoff);
// there is a distance bigger than DCKCOFF in the same fragment. 
// Increase dckcoff
	   return(1);
	} else {
// there is a distance smaller than DCKCOFF in the same fragment
	   fprintf(stderr,"there is a distance smaller than DCKCOFF in the same fragment\n");
	   return(0);
	}
   } else {
	fprintf(stderr,"there is NO ACC/DON pair in the same fragment\n");
// there is  NO ACC/DON pair in the same fragment. 
	return(1);
   }
}

void Reduce_Pairs(int FiltAD,int *npairl,int *ADPAIR1,int *ADPAIR2,int *PAIRT)
{
   int i,j,n,np;

   n = *npairl; np = 0;

   for (i=0; i < n; i++) {
	if (PAIRT[i] == FiltAD) {
	   
	   ADPAIR1[np] = ADPAIR1[i];
	   ADPAIR2[np] = ADPAIR2[i];
	   PAIRT[np] = PAIRT[i];
	   np++;
	}
   }
   *npairl = np;

if (debugdck) fprintf(stderr,"Reduce_Pairs: New np %d\n\n",np);
if (debugdck) fprintf(stderr,"Reduce_Pairs: ADPAIR1[0] %d ADPAIR2[0] %d\n\n",ADPAIR1[0],ADPAIR2[0]);

}

int Monitor_AccDon_Conformers(n1,n2,p1,p2,npair,npairl,ADPAIR1,ADPAIR2,PAIRT)
int n1;
int n2;
int *p1;
int *p2;
int *npair;
int *npairl;
int *ADPAIR1;
int *ADPAIR2;
int *PAIRT;
{

   int i,j,l,Conf,P1,P2;
   double r,tt,toangs2,DCKCOFF2,*R2MINAD,*R2MINAA,*R2MINDD;
   double R2MINEST,R2MINADEST,R2MINAAEST,R2MINDDEST;

   R2MINAD = (double *) malloc(sizeof(double)*ntrif);
   R2MINAA = (double *) malloc(sizeof(double)*ntrif);
   R2MINDD = (double *) malloc(sizeof(double)*ntrif);

   toangs2 = TOANG*TOANG;
   DCKCOFF2 = dckcoff*dckcoff;

   for (i=0; i < ntrif; i++) {
	R2MINAD[i] = BIGD;
	R2MINAA[i] = BIGD;
	R2MINDD[i] = BIGD;
   }


// acc - don combination

   *npair = 0; *npairl = 0;

   for (i=0; i < n1; i++) {

     for (j=0; j < n2; j++) {

	P1 = lind[p1[i]];
	P2 = lind[p2[j]];

	if (ligtyp[P2]->ohlig && ligtyp[P2]->ohsame < 0) {

	   if (CmpORI(ligtyp[P1]->ORI,ligtyp[P2]->ORI) &&
		ligtyp[P1]->conf == ligtyp[P2]->conf &&
		ligtyp[P1]->link != ligtyp[P2]->link) {

	      Conf = ligtyp[P1]->conf;
	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[P1]->ORI[l] - ligtyp[P2]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 < R2MINAD[Conf] && r*toangs2 > DCKCMIN*DCKCMIN) {
 		R2MINAD[Conf] = r*toangs2;
		*npair = *npair + 1;
		if ((ligtyp[P1]->link != ligtyp[P2]->link) || 
		    !ligtyp[P1]->ohlig || !ligtyp[P2]->ohlig) 
			ADPAIR1[*npairl] =  ligtyp[P1]->frag[0];
			ADPAIR2[*npairl] =  ligtyp[P2]->frag[0];
			PAIRT[*npairl] =  1;
			*npairl = *npairl + 1;
	      }

	   }
	}
     }
   }

// acc - acc combination

   for (i=0; i < n1; i++) {

     for (j=0; j < n1; j++) {

	if (i != j) {

	   P1 = lind[p1[i]];
	   P2 = lind[p1[j]];

	   if (CmpORI(ligtyp[P1]->ORI,ligtyp[P2]->ORI) &&
		ligtyp[P1]->conf == ligtyp[P2]->conf) {

	      Conf = ligtyp[P1]->conf;

	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[P1]->ORI[l] - ligtyp[P2]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (ligtyp[P1]->type == H_ACC && ligtyp[P2]->type == H_ACC) {
	         if (r*toangs2 < R2MINAA[Conf] 
			&& r*toangs2 > DCKCMIN*DCKCMIN) {
 			R2MINAA[Conf] = r*toangs2;
			*npair = *npair + 1;
			ADPAIR1[*npairl] =  ligtyp[P1]->frag[0];
			ADPAIR2[*npairl] =  ligtyp[P2]->frag[0];
			PAIRT[*npairl] =  2;
			*npairl = *npairl + 1;
	         }
	      }

	   }
	}
     }
   }

// don - don combination

   for (i=0; i < n2; i++) {

     for (j=0; j < n2; j++) {

	if (i != j) {

	 P1 = lind[p2[i]];
	 P2 = lind[p2[j]];

	 if ((ligtyp[P1]->ohlig && ligtyp[P1]->ohsame < 0) &&
	     (ligtyp[P2]->ohlig && ligtyp[P2]->ohsame < 0)) {
	   if (CmpORI(ligtyp[P1]->ORI,ligtyp[P2]->ORI) &&
		ligtyp[P1]->conf == ligtyp[P2]->conf) {

	      Conf = ligtyp[P1]->conf;
	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[P1]->ORI[l] - ligtyp[P2]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 < R2MINDD[Conf] && r*toangs2 > DCKCMIN*DCKCMIN) {
 		R2MINDD[Conf] = r*toangs2;
		*npair = *npair + 1;
		ADPAIR1[*npairl] =  ligtyp[P1]->frag[0];
		ADPAIR2[*npairl] =  ligtyp[P2]->frag[0];
		PAIRT[*npairl] =  3;
		*npairl = *npairl + 1;
	      }

	   }
	 }
	}
     }
   }

   R2MINADEST = -BIGD;
   R2MINAAEST = -BIGD;
   R2MINDDEST = -BIGD;

   for (i=0; i < ntrif; i++) {
	if (R2MINAD[i] != BIGD) {
	   if (R2MINAD[i] > R2MINADEST) R2MINADEST = R2MINAD[i];
	}
	if (R2MINAA[i] != BIGD) {
	   if (R2MINAA[i] > R2MINAAEST) R2MINAAEST = R2MINAA[i];
	}
	if (R2MINDD[i] != BIGD) {
	   if (R2MINDD[i] > R2MINDDEST) R2MINDDEST = R2MINDD[i];
	}
   }

   R2MINEST = R2MINADEST;
//   if (R2MINAAEST < R2MINEST && R2MINAAEST != -BIGD) R2MINEST = R2MINAAEST;
//   if (R2MINDDEST < R2MINEST && R2MINDDEST != -BIGD) R2MINEST = R2MINDDEST;
   if (R2MINEST < R2MINAAEST) R2MINEST = R2MINAAEST;
   if (R2MINEST < R2MINDDEST) R2MINEST = R2MINDDEST;

   safefree((void **)&R2MINAD);
   safefree((void **)&R2MINAA);
   safefree((void **)&R2MINDD);

   if (R2MINEST != -BIGD) {
	if (R2MINEST > DCKCOFF2) {
	   dckcoff = 15.0;
	   FiltAD = 0;
	   if (R2MINEST == R2MINADEST) FiltAD = 1;
	   if (R2MINEST == R2MINAAEST) FiltAD = 2;
	   if (R2MINEST == R2MINDDEST) FiltAD = 3;
	   Reduce_Pairs(FiltAD,npairl,ADPAIR1,ADPAIR2,PAIRT);

	   if (debugdck) fprintf(stderr,"NEW DCKCOFF %.3f\n\n",dckcoff);
// there is a distance bigger  than DCKCOFF in the same fragment. 
// Increase dckcoff
	   return(1);
	} else {
// there is a distance smaller than DCKCOFF in the same fragment
	   FiltAD = 0;
	   if (R2MINEST == R2MINADEST) FiltAD = 1;
	   if (R2MINEST == R2MINAAEST) FiltAD = 2;
	   if (R2MINEST == R2MINDDEST) FiltAD = 3;
	   return(0);
	}
   } else {

// there is a NO ACC/DON pair in the same fragment. 

	return(1);
   }
}

int OneLine(int spec, float *c1, float *c2, float *c3)
{
   int j;
   float v1[3],v2[3],v3[3],cosa;

   if (spec == 1) {
	for (j=0;j < 3; j++) {
	   v1[j] = (c3[j] - c2[j]);
	   v2[j] = (c1[j] - c2[j]);
	}
   } else if (spec == 2) {
	for (j=0;j < 3; j++) {
	   v1[j] = (c3[j] - c1[j]);
	   v2[j] = (c2[j] - c1[j]);
	}
   } else if (spec == 3) {
	for (j=0;j < 3; j++) {
	   v1[j] = (c2[j] - c1[j]);
	   v2[j] = (c3[j] - c1[j]);
	}
   }
   vecnrm(v1); vecnrm(v2);
   IMPRD(v1,v2,&cosa,1);

//fprintf(stderr,"OneLine: 1.0 - ABS(cosa) %.3f\n",1.0 - ABS(cosa));

   if (1.0 - ABS(cosa) < 0.1) {
	return(1);
   } else {
	return(0);
   }
   
}

int IsSpec(int type1,int type2,int type3)
{

// This function determines wether there is one of the triangle
// corners is not a Hydrogen bond ACCeptor or DONor
// If this is the case the function return the number of the corner
// that is not H_ACC or H_DON

   if (type1 == H_ACC && type2 == H_DON && 
      (type3 != H_ACC && type3 != H_DON)) return(3);

   if (type1 == H_DON && type2 == H_ACC && 
      (type3 != H_ACC && type3 != H_DON)) return(3);

   if (type1 == H_DON && type2 == H_DON && 
      (type3 != H_ACC && type3 != H_DON)) return(3);

   if (type1 == H_ACC && type2 == H_ACC && 
      (type3 != H_ACC && type3 != H_DON)) return(3);

   if (type1 == H_ACC && type2 == H_DON && 
      (type3 != H_ACC && type3 != H_DON)) return(3);

// ====================================================

   if (type2 == H_ACC && type3 == H_DON && 
      (type1 != H_ACC && type1 != H_DON)) return(1);

   if (type2 == H_DON && type3 == H_ACC && 
      (type1 != H_ACC && type1 != H_DON)) return(1);

   if (type2 == H_DON && type3 == H_DON && 
      (type1 != H_ACC && type1 != H_DON)) return(1);

   if (type2 == H_ACC && type3 == H_ACC && 
      (type1 != H_ACC && type1 != H_DON)) return(1);

   if (type2 == H_ACC && type3 == H_DON && 
      (type1 != H_ACC && type1 != H_DON)) return(1);

// ====================================================


   if (type1 == H_ACC && type3 == H_DON && 
      (type2 != H_ACC && type2 != H_DON)) return(2);

   if (type1 == H_DON && type3 == H_ACC && 
      (type2 != H_ACC && type2 != H_DON)) return(2);

   if (type1 == H_DON && type3 == H_DON && 
      (type2 != H_ACC && type2 != H_DON)) return(2);

   if (type1 == H_ACC && type3 == H_ACC && 
      (type2 != H_ACC && type2 != H_DON)) return(2);

   if (type1 == H_ACC && type3 == H_DON && 
      (type2 != H_ACC && type2 != H_DON)) return(2);
}

void Harvest_Triples(n1,n2,n3,p1,p2,p3)
int n1;
int n2;
int n3;
int *p1;
int *p2;
int *p3;
{
// Harvest Triples creates triples of interaction points by sampling
// three points from different or the same interaction arrays p1,p2,p3
// where each distance between the three interaction points
// must be smaller than DCKCOFF
//
// currently only triples belonging to ONE fragment are sampled !!!
//

   int i,j,k,l,p1isp2,p1isp3,p2isp3,SingleFrag,SameFrag,Conf;
   int OHSAME12,OHSAME13,OHSAME23,spec;
   double r,p,q,dd,tt,toangs2,DCKCOFF2;
   float rr,pp,qq;

   toangs2 = TOANG*TOANG;
   DCKCOFF2 = dckcoff*dckcoff;

   p1isp2 = 0; p1isp3 = 0; p2isp3 = 0;

   if (p1 == p2) p1isp2 = 1;
   if (p1 == p3) p1isp3 = 1;
   if (p2 == p3) p2isp3 = 1;

   for (i=0; i < n1; i++) {

     for (j=0; j < n2; j++) {

	if (!p1isp2 || (p1isp2 && i != j)) {

	   OHSAME12 = 0;
	   if (ligtyp[p1[i]]->ohsame && ligtyp[p2[j]]->ohsame) {
		if (ABS(ligtyp[p1[i]]->ohsame) == ABS(ligtyp[p2[j]]->ohsame)) 
			OHSAME12 = 1;
	   }
	   if (CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p2[j]]->ORI) &&
		ligtyp[p1[i]]->conf == ligtyp[p2[j]]->conf && !OHSAME12) {

	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p2[j]]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (r*toangs2 > DCKCOFF2) continue;

	      for (k=0; k < n3; k++) {

		Conf = -1;

		OHSAME13 = 0;
		if (ligtyp[p1[i]]->ohsame && ligtyp[p3[k]]->ohsame) {
		    if (ABS(ligtyp[p1[i]]->ohsame) == 
			ABS(ligtyp[p3[k]]->ohsame)) 
				OHSAME13 = 1;
		}

		OHSAME23 = 0;
		if (ligtyp[p2[j]]->ohsame && ligtyp[p3[k]]->ohsame) {
		    if (ABS(ligtyp[p2[j]]->ohsame) == 
			ABS(ligtyp[p3[k]]->ohsame)) 
				OHSAME23 = 1;
		}

		if ((!p1isp3 || (p1isp3 && i != k) &&
		     !p2isp3 || (p2isp3 && j != k) ) &&
		    CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p3[k]]->ORI) &&
		    CmpORI(ligtyp[p2[j]]->ORI,ligtyp[p3[k]]->ORI) &&
		    ligtyp[p2[j]]->conf == ligtyp[p3[k]]->conf &&
		    !OHSAME13 && !OHSAME23
		   ) {

		   if ( ligtyp[p1[i]]->conf != -1 ||
			ligtyp[p2[j]]->conf != -1 || 
			ligtyp[p3[k]]->conf != -1) {
			Conf = ligtyp[p1[i]]->conf;
		   }

		   SameFrag = 0;
		   if (ligtyp[p1[i]]->frag[0] == ligtyp[p2[j]]->frag[0] && 
			ligtyp[p1[i]]->frag[0] == ligtyp[p3[k]]->frag[0])
			SameFrag = 1;

		   SingleFrag = 0;
		   if (ligtyp[p1[i]]->nfrag == 1 && ligtyp[p2[j]]->nfrag == 1 &&
			ligtyp[p3[k]]->nfrag == 1) SingleFrag = 1;

		   if ((SameFrag && SingleFrag) || Conf != -1) {

			p = 0.0; q = 0.0;

			for (l=0; l < 3; l++) {
			   tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p3[k]]->ORI[l];
			   p = p + tt*tt;
			   tt = ligtyp[p2[j]]->ORI[l] - ligtyp[p3[k]]->ORI[l];
			   q = q + tt*tt;
			}

			if (p*toangs2 > DCKCOFF2) continue;
			if (q*toangs2 > DCKCOFF2) continue;

			TriS[ntriS].grp[0] = ligtyp[p1[i]]->type;
			TriS[ntriS].atindx[0] = ligtyp[p1[i]]->atom[0];
			TriS[ntriS].lig[0] = p1[i];
			TriS[ntriS].ohlig[0] = ligtyp[p1[i]]->ohlig;

			TriS[ntriS].grp[1] = ligtyp[p2[j]]->type;
			TriS[ntriS].atindx[1] = ligtyp[p2[j]]->atom[0];
			TriS[ntriS].lig[1] = p2[j];
			TriS[ntriS].ohlig[1] = ligtyp[p2[j]]->ohlig;

			TriS[ntriS].grp[2] = ligtyp[p3[k]]->type;
			TriS[ntriS].atindx[2] = ligtyp[p3[k]]->atom[0];
			TriS[ntriS].lig[2] = p3[k];
			TriS[ntriS].ohlig[2] = ligtyp[p3[k]]->ohlig;

			for (l=0; l < 3; l++) {
			   TriS[ntriS].p1[l] = (float) ligtyp[p1[i]]->ORI[l];
	      		   TriS[ntriS].p2[l] = (float) ligtyp[p2[j]]->ORI[l];
			   TriS[ntriS].p3[l] = (float) ligtyp[p3[k]]->ORI[l];
			}

			spec = IsSpec(ligtyp[p1[i]]->type,
					ligtyp[p2[j]]->type,
					ligtyp[p3[k]]->type);

			if (OneLine(spec,
				TriS[ntriS].p1,TriS[ntriS].p2,TriS[ntriS].p3)){
			   TriS[ntriS].oneline = 1;
			} else {
			   TriS[ntriS].oneline = 0;
			}

			TriS[ntriS].frag = ligtyp[p2[j]]->frag[0];
			TriS[ntriS].conf = Conf;
			TriS[ntriS].nconf = 0;
			TriS[ntriS].active = 1;

			ntriS++;
			if (ntriS == MAXSTRI - 1) return;
		   }
	        }
	      }
	   }
	}
     }
   }
}

int DetAD(int i, int j)
{
   if (ligtyp[i]->type == H_DON && ligtyp[j]->type == H_ACC) return(1);
   if (ligtyp[i]->type == H_ACC && ligtyp[j]->type == H_DON) return(1);
   if (ligtyp[i]->type == H_ACC && ligtyp[j]->type == H_ACC) return(2);
   if (ligtyp[i]->type == H_DON && ligtyp[j]->type == H_DON) return(3);
   return(0);
}

void Harvest_Triples_NoFrag(n1,n2,n3,p1,p2,p3)
int n1;
int n2;
int n3;
int *p1;
int *p2;
int *p3;
{
// Harvest Triples creates triples of interaction points by sampling
// three points from different or the same interaction arrays p1,p2,p3
// where each distance between the three interaction points
// must be smaller than DCKCOFF
//
// Interaction points from two different fragments are probed if they
// satisfy the enlarged DCKCOFF
//

   int i,j,k,l,p1isp2,p1isp3,p2isp3,SingleFrag,SameFrag,Conf;
   int OHSAME12,OHSAME13,OHSAME23,spec;
   int D12,D13,D23;
   double r,p,q,dd,tt,toangs2,DCKCOFF2;
   float rr,pp,qq,cosa;

   toangs2 = TOANG*TOANG;
   DCKCOFF2 = dckcoff*dckcoff;

   p1isp2 = 0; p1isp3 = 0; p2isp3 = 0;
   D12 = 0; D13 = 0; D23 = 0;

   if (p1 == p2) p1isp2 = 1;
   if (p1 == p3) p1isp3 = 1;
   if (p2 == p3) p2isp3 = 1;

   for (i=0; i < n1; i++) {

     for (j=0; j < n2; j++) {

	if (!p1isp2 || (p1isp2 && i != j)) {

	   OHSAME12 = 0;
	   if (ligtyp[p1[i]]->ohsame && ligtyp[p2[j]]->ohsame) {
		if (ABS(ligtyp[p1[i]]->ohsame) == 
		    ABS(ligtyp[p2[j]]->ohsame))
			OHSAME12 = 1;
	   }

	   if (CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p2[j]]->ORI) &&
		ligtyp[p1[i]]->conf == ligtyp[p2[j]]->conf && !OHSAME12) {
	      r = 0.0;

	      for (l=0; l < 3; l++) {
	         tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p2[j]]->ORI[l];
	         r = r + tt*tt;
	      }

	      if (DetAD(p1[i],p2[j]) == FiltAD) {
		 if (r*toangs2 > DCKCOFF2) continue;
//		 if (r*toangs2 < 100.09) continue;
		 D12 = 1;
	      } else {
		 if (r*toangs2 > 100.0) continue;
	      }

	      for (k=0; k < n3; k++) {

		Conf = -1;
		OHSAME13 = 0;
		if (ligtyp[p1[i]]->ohsame && ligtyp[p3[k]]->ohsame) {
		   if (ABS(ligtyp[p1[i]]->ohsame) == 
		       ABS(ligtyp[p3[k]]->ohsame))
			OHSAME13 = 1;
		}

		OHSAME23 = 0;
		if (ligtyp[p2[j]]->ohsame && ligtyp[p3[k]]->ohsame) {
		    if (ABS(ligtyp[p2[j]]->ohsame) == 
			ABS(ligtyp[p3[k]]->ohsame)) 
				OHSAME23 = 1;
		}

		if ((!p1isp3 || (p1isp3 && i != k) &&
		     !p2isp3 || (p2isp3 && j != k) ) &&
		    CmpORI(ligtyp[p1[i]]->ORI,ligtyp[p3[k]]->ORI) &&
		    CmpORI(ligtyp[p2[j]]->ORI,ligtyp[p3[k]]->ORI) &&
		    ligtyp[p1[i]]->conf == ligtyp[p3[k]]->conf &&
		    ligtyp[p2[j]]->conf == ligtyp[p3[k]]->conf && 
		    !OHSAME13 && !OHSAME23
		   ) {

		   Conf = ligtyp[p1[i]]->conf;

		   if (Conf != -1) {

			p = 0.0; q = 0.0;

			for (l=0; l < 3; l++) {
			   tt = ligtyp[p1[i]]->ORI[l] - ligtyp[p3[k]]->ORI[l];
			   p = p + tt*tt;
			   tt = ligtyp[p2[j]]->ORI[l] - ligtyp[p3[k]]->ORI[l];
			   q = q + tt*tt;
			}

			if (DetAD(p1[i],p3[k]) == FiltAD) {
	 		   if (p*toangs2 > DCKCOFF2) continue;
			} else {
			   if (p*toangs2 > 100.0) continue;
			}

			if (DetAD(p2[j],p3[k]) == FiltAD) {
	 		   if (q*toangs2 > DCKCOFF2) continue;
			} else {
			   if (q*toangs2 > 100.0) continue;
			}

	if (DetAD(p1[i],p2[j]) != 0) {
	   if (DetAD(p1[i],p3[k]) == 0 && DetAD(p2[j],p3[k]) == 0) {
		if (p*toangs2 > 100.00 && q*toangs2 > 100.00) continue;
	   } else {
//		continue;
	   }
	} else {
		continue;
	}

	if (DetAD(p1[i],p3[k]) != 0) {
	   if (p*toangs2 < 100.00) continue;
	   if (DetAD(p1[i],p2[j]) == 0 && DetAD(p2[j],p3[k]) == 0) {
		if (!((q*toangs2 < 100.00 && r*toangs2 > 100.00) ||
		      (r*toangs2 < 100.00 && q*toangs2 > 100.00)) ) continue;
	   } else {
		continue;
	   }
	}

	if (DetAD(p2[j],p3[k]) != 0) {
	   if (q*toangs2 < 100.00) continue;
	   if (DetAD(p1[i],p2[j]) == 0 && DetAD(p1[i],p3[k]) == 0) {
		if (!((p*toangs2 < 100.00 && r*toangs2 > 100.00) ||
		      (r*toangs2 < 100.00 && p*toangs2 > 100.00)) ) continue;
	   } else {
		continue;
	   }
	}


			TriS[ntriS].grp[0] = ligtyp[p1[i]]->type;
			TriS[ntriS].atindx[0] = ligtyp[p1[i]]->atom[0];
			TriS[ntriS].lig[0] = p1[i];
			TriS[ntriS].ohlig[0] = ligtyp[p1[i]]->ohlig;

			TriS[ntriS].grp[1] = ligtyp[p2[j]]->type;
			TriS[ntriS].atindx[1] = ligtyp[p2[j]]->atom[0];
			TriS[ntriS].lig[1] = p2[j];
			TriS[ntriS].ohlig[1] = ligtyp[p2[j]]->ohlig;

			TriS[ntriS].grp[2] = ligtyp[p3[k]]->type;
			TriS[ntriS].atindx[2] = ligtyp[p3[k]]->atom[0];
			TriS[ntriS].lig[2] = p3[k];
			TriS[ntriS].ohlig[2] = ligtyp[p3[k]]->ohlig;

			for (l=0; l < 3; l++) {
			   TriS[ntriS].p1[l] = (float) ligtyp[p1[i]]->ORI[l];
	      		   TriS[ntriS].p2[l] = (float) ligtyp[p2[j]]->ORI[l];
			   TriS[ntriS].p3[l] = (float) ligtyp[p3[k]]->ORI[l];
			}

			TriS[ntriS].conf = Conf;
//			TriS[ntriS].nconf = 0;
			TriS[ntriS].nconf = 1;

			if (TriS[ntriS].conf == -1) {
			   TriS[ntriS].frag = ligtyp[p2[j]]->frag[0];
			} else {
			   TriS[ntriS].frag = -1;
			   TriS[ntriS].frags[0] = ligtyp[p1[i]]->frag[0];
			   TriS[ntriS].frags[1] = ligtyp[p2[j]]->frag[0];
			   TriS[ntriS].frags[2] = ligtyp[p3[k]]->frag[0];
			}

			spec = IsSpec(ligtyp[p1[i]]->type,
					ligtyp[p2[j]]->type,
					ligtyp[p3[k]]->type);

			if (OneLine(spec,
				TriS[ntriS].p1,TriS[ntriS].p2,TriS[ntriS].p3)){
			   TriS[ntriS].oneline = 1;
			} else {
			   TriS[ntriS].oneline = 0;
			}

			TriS[ntriS].active = 1;

			ntriS++;
			if (ntriS == MAXSTRI - 1) return;
		   }
	        }
	      }
	   }
	}
     }
   }
}

void prtypes(ityp,n,iacc,nacc,idon,ndon,iphec,nphec,ipher,npher,iaro,naro)
INCRSTRU **ityp;
int n;
int *iacc;
int *nacc;
int *idon;
int *ndon;
int *iphec;
int *nphec;
int *ipher;
int *npher;
int *iaro;
int *naro;
{
   int i;

   *nacc = 0; *ndon = 0; *nphec = 0; *npher = 0; *naro = 0;

   if (n == 0) return;

   for (i=0; i < n; i++) {
	switch(ityp[i]->type) {
	case H_ACC:
	   fprintf(stderr,"%d H_ACC conf %d\n",i,ityp[i]->conf);
	   iacc[*nacc] = i;
	   (*nacc)++;
	   break;
	case H_DON:
	   fprintf(stderr,"%d H_DON conf %d\n",i,ityp[i]->conf);
	   idon[*ndon] = i;
	   (*ndon)++;
	   break;
	case PHENYL_CENTER:
	   fprintf(stderr,"%d PHENYL_CENTER conf %d\n",i,ityp[i]->conf);
	   iphec[*nphec] = i;
	   (*nphec)++;
	   break;
	case PHENYL_RING:
	   fprintf(stderr,"%d PHENYL_RING conf %d\n",i,ityp[i]->conf);
	   ipher[*npher] = i;
	   (*npher)++;
	   break;
	case CH:
	case CH2:
	case CH3:
	case SULFUR:
	case ARO:
	   fprintf(stderr,"%d ARO_GROUP conf %d\n",i,ityp[i]->conf);
	   iaro[*naro] = i;
	   (*naro)++;
	   break;
	default:
	   fprintf(stderr,"%d Other\n",i);
	}
   }

   fprintf(stderr,"\n");
}

void Prtypes(ityp,n,iacc,nacc,idon,ndon,iphec,nphec,ipher,npher,iaro,naro)
INCRSTRU **ityp;
int n;
int *iacc;
int *nacc;
int *idon;
int *ndon;
int *iphec;
int *nphec;
int *ipher;
int *npher;
int *iaro;
int *naro;
{
   int i;

   *nacc = 0; *ndon = 0; *nphec = 0; *npher = 0; *naro = 0;

   if (n == 0) return;

   for (i=0; i < n; i++) {
	switch(ityp[i]->type) {
	case H_ACC:
	   iacc[*nacc] = i;
	   (*nacc)++;
	   break;
	case H_DON:
	   idon[*ndon] = i;
	   (*ndon)++;
	   break;
	case PHENYL_CENTER:
	   iphec[*nphec] = i;
	   (*nphec)++;
	   break;
	case PHENYL_RING:
	   ipher[*npher] = i;
	   (*npher)++;
	   break;
	case CH:
	case CH2:
	case CH3:
	case SULFUR:
	case ARO:
	   iaro[*naro] = i;
	   (*naro)++;
	   break;
	default:
	   break;
	}
   }

}

void selarr(grp,n,arr,pacc,pdon,pphec,ppher,paro,
	   npacc,npdon,npphec,nppher,nparo)
int grp;
int *n;
int **arr;
int *pacc;
int *pdon;
int *pphec;
int *ppher;
int *paro;
int npacc;
int npdon;
int npphec;
int nppher;
int nparo;
{

// select the correct array depending on group and passes it on to *arr

	switch(grp) {
	case H_ACC_GROUP:
		*arr = pacc;
		*n  =  npacc;
		break;
	case H_DON_GROUP:
		*arr = pdon;
		*n  =  npdon;
		break;
	case PHC_GROUP:
		*arr = pphec;
		*n  =  npphec;
		break;
	case PHR_GROUP:
		*arr = ppher;
		*n  =  nppher;
		break;
	case ARO_GROUP:
		*arr = paro;
		*n  =  nparo;
		break;
	}
}


void getpdb_(ires,ipdb,ihpdb)
int *ires;
int *ipdb;
int *ihpdb;
{

   getpdd_(ires,ipdb,ihpdb,xyzp->ianz,xyzp->iresid,xyzp->ipdbt); 
}

void pdbstd_(istat,doscnd)
int *istat;
int *doscnd;
{
  int i;
  int iszhnt = 0;

  pdbsiz_(&iszhnt);
  if (iszhnt > *xyzp->mxnat) allcoo_(&iszhnt,&ZERO);
  setid_(&FOUR,&ZERO,xyzp->isurf,xyzp->iresid,xyzp->ipdbt);

  pdbsdd_(istat,doscnd,
	xyzp->coo,xyzp->ianz,xyzp->iaton,xyzp->iresid,xyzp->iconn,xyzp->ityp,
        &calfptr->ncalf,calfptr->ianf,calfptr->islu,
        &calfptr->nchain,calfptr->iamino,calfptr->ihet,
        calfptr->isal,calfptr->irsnr,calfptr->achain,
	&calfptr->ihashb,&calfptr->ishoh);


  if (*istat == -1) {
	hetptr.NHetAtm = 0;
	allcoo_(&addat,&ZERO);
	pdbsdd_(istat,doscnd,
	   xyzp->coo,xyzp->ianz,xyzp->iaton,xyzp->iresid,xyzp->iconn,
	   xyzp->ityp,&calfptr->ncalf,calfptr->ianf,calfptr->islu,
           &calfptr->nchain,calfptr->iamino,calfptr->ihet,
           calfptr->isal,calfptr->irsnr,calfptr->achain,
	   &calfptr->ihashb,&calfptr->ishoh);
  }
}

void Gen_triples_conf()
{
   int i,j,l;

   for (i=0; i < ntriS; i++) {
     if (TriS[i].active) {

	Tri1.grp[0] = TriS[i].grp[0];
	Tri1.grp[1] = TriS[i].grp[1];
	Tri1.grp[2] = TriS[i].grp[2];
	Tri1.lig[0] = TriS[i].lig[0];
	Tri1.lig[1] = TriS[i].lig[1];
	Tri1.lig[2] = TriS[i].lig[2];
	Tri1.ohlig[0] = TriS[i].ohlig[0];
	Tri1.ohlig[1] = TriS[i].ohlig[1];
	Tri1.ohlig[2] = TriS[i].ohlig[2];
	for (l=0; l < 3; l++) {
	   Tri1.p1[l] = TriS[i].p1[l];
	   Tri1.p2[l] = TriS[i].p2[l];
	   Tri1.p3[l] = TriS[i].p3[l];
	}
	Tri1.frag = TriS[i].frag;
	Tri1.conf = TriS[i].conf;
	Tri1.nconf = TriS[i].nconf;
	if (TriS[i].conf != -1) {
	   Tri1.frags[0] = TriS[i].frags[0];
	   Tri1.frags[1] = TriS[i].frags[1];
	   Tri1.frags[2] = TriS[i].frags[2];
	}

// convert specific group H_ACC to general H_ACC_GROUP

	Calc_Centroid(&Tri1);

	TriS[i].d12 = Tri1.d12;
	TriS[i].d13 = Tri1.d13;
	TriS[i].d23 = Tri1.d23;
	Tri1.oneline = TriS[i].oneline;

	Calc_Centroid(&Tri1);

	if (Find_Lig_Conf2(i)) Find_Triangle_Match(Tri1,i,0);
	if ((ligtyp[Tri1.lig[0]]->type == H_ACC &&
	     ligtyp[Tri1.lig[1]]->type == H_DON) ||
	    (ligtyp[Tri1.lig[1]]->type == H_ACC &&
	     ligtyp[Tri1.lig[0]]->type == H_DON) &&
	    (ligtyp[Tri1.lig[2]]->type == PHENYL_CENTER ||
	     ligtyp[Tri1.lig[2]]->type == PHENYL_RING)) {

		if (Find_Lig_Conf2(i)) Find_Triangle_Match(Tri1,i,1);
	}
	if (ntris == MAXTRI - 1) return;

     }
   }

}

void Gen_triples()
{
   int i,j,l;

   for (i=0; i < ntriS; i++) {
     if (TriS[i].active) {

	Tri1.grp[0] = TriS[i].grp[0];
	Tri1.grp[1] = TriS[i].grp[1];
	Tri1.grp[2] = TriS[i].grp[2];
	Tri1.lig[0] = TriS[i].lig[0];
	Tri1.lig[1] = TriS[i].lig[1];
	Tri1.lig[2] = TriS[i].lig[2];
	Tri1.ohlig[0] = TriS[i].ohlig[0];
	Tri1.ohlig[1] = TriS[i].ohlig[1];
	Tri1.ohlig[2] = TriS[i].ohlig[2];
	for (l=0; l < 3; l++) {
	   Tri1.p1[l] = TriS[i].p1[l];
	   Tri1.p2[l] = TriS[i].p2[l];
	   Tri1.p3[l] = TriS[i].p3[l];
	}
	Tri1.frag = TriS[i].frag;
	Tri1.conf = TriS[i].conf;
	Tri1.nconf = TriS[i].nconf;
	if (TriS[i].conf != -1) {
	   Tri1.frags[0] = TriS[i].frags[0];
	   Tri1.frags[1] = TriS[i].frags[1];
	   Tri1.frags[2] = TriS[i].frags[2];
	}

// convert specific group H_ACC to general H_ACC_GROUP

	Calc_Centroid(&Tri1);

	TriS[i].d12 = Tri1.d12;
	TriS[i].d13 = Tri1.d13;
	TriS[i].d23 = Tri1.d23;
	Tri1.oneline = TriS[i].oneline;

	Calc_Centroid(&Tri1);

	Find_Triangle_Match(Tri1,i,0);
	if ((ligtyp[Tri1.lig[0]]->type == H_ACC &&
	     ligtyp[Tri1.lig[1]]->type == H_DON) ||
	    (ligtyp[Tri1.lig[1]]->type == H_ACC &&
	     ligtyp[Tri1.lig[0]]->type == H_DON) &&
	    (ligtyp[Tri1.lig[2]]->type == PHENYL_CENTER ||
	     ligtyp[Tri1.lig[2]]->type == PHENYL_RING)) {

		Find_Triangle_Match(Tri1,i,1);
	}
	if (ntris == MAXTRI - 1) return;

     }
   }

}

void OrgLig()
{
     int i,j,k;
     int grpj,grpk;
     double t0[3],R1[4][4];
     float etot,OutO[3];

     for (i=0; i < 3; i++) t0[i] = 0.0;
     for (i=0; i < 4; i++) {
        for (j=0; j < 4; j++) {
	  if (i == j) {
	   R1[i][j] = 1.0;
	  } else {
	   R1[i][j] = 0.0;
	  }
        }
     }

     if (TriArr[0] == NULL) TriAll(&TriArr[0]);

     allConf(&TriArr[0]->coo,ndocka);

     if (TriArr[0]->coo == NULL) return;

     for (i=0; i<ndocka; i++) {
	for (j=0; j<3; j++) {
	   TriArr[0]->coo[i*3+j] = DCKxyz.coo[i*3+j];
	}
     }

     prE = 1;
     etot = 0.0;
     for (j=0; j < lintp; j++) {
	grpj = Find_Group(ligtyp[j]->type);
	grpj = Find_Matching_Group(grpj);
	for (k=0; k < nintp; k++) {
	   grpk = Find_Group(inttyp[k]->type);
	   if (grpj == grpk) {
	      etot = etot + 
	      CalInt(k,j,ligtyp[j]->points,t0,R1,R1,OutO,OutO,1);
	   }
	}
     }
     TriArr[0]->e12 = etot;
     prE = 0;
     ntris++;
}

void RemCC_One(L)
int L;
{
// Check triangle ligand coordinates TriArr[L]->coo for bumps against 
// all atoms of the proein
// If the triangle bumps remove it.
//
// RemCC_One is called once after replacing the triangle with all
// conformers in Map_Conformers
//

    int i,j,k,l,ires;
    float tt,dd;
    double ddd,ttd,CLOSED;

    if (*ipdbon && calfptr->ncalf != 0) {
	for (ires = 1; ires < calfptr->ncalf+1; ires++ ) {

   	   getpdb_(&ires,ipdb,ihpdb);

	   CLOSED = CLOSEC/toangs;

	   for (i=0; i<MXSYM; i++) {
		if (ipdb[i] > 0) {
		   if (TriArr[L] != NULL) {
			for (k = 0; k < ndocka; k++ ) {
			   ddd = 0.0;
			   for (l = 0; l < 3; l++ ) {
				ttd = xyzp->coo[(ipdb[i]-1)*3+l] - 
					TriArr[L]->coo[k*3+l];
				ddd = ddd + ttd*ttd;
			   }
			   if (sqrt(ddd) < CLOSED) {
	        	   	TriCooSafeFree(L);
	   		   	TriSafeFreeTxt(L,"RemCC_One",
					"Reason: close contact");
				ntris--;
				break;
			   }
			}
		   }
		}
	   }

	   for (i=0; i<3*MXHSYM; i++) {
		if (ihpdb[i] > 0) {
		   if (TriArr[L] != NULL) {
			for (k = 0; k < ndocka; k++ ) {
			   ddd = 0.0;
			   for (l = 0; l < 3; l++ ) {
				ttd = xyzp->coo[(ihpdb[i]-1)*3+l] - 
					TriArr[L]->coo[k*3+l];
				ddd = ddd + ttd*ttd;
			   }
			   if (sqrt(ddd) < CLOSED) {
	        	   	TriCooSafeFree(L);
	   		   	TriSafeFreeTxt(L,"RemCC_One Hydrogen",
					"Reason: close contact");
				ntris--;
				break;
			   }
			}
		   }
		}
	   }


	}
    }

}

float Atom_Distance(float* xyz1, float* xyz2)
{
   int i;
   float d,d2,dd;

   d2 = 0.0;
   for (i=0; i<3; i++) {
	dd = xyz1[i] - xyz2[i];
	d2 = d2 + dd*dd;
   }
   
   d = sqrt(d2);

   return(d);

}

#define DISTOL  4.0
#define DISFRAC 0.2

int PrtConf(TRISTRU *Tri, int itri)
{
   int i;

   for (i=0; i < nchk; i++) {
	if (Match_tri(Tri,
		TriCHK[i]->lig[0],TriCHK[i]->lig[1],TriCHK[i]->lig[2],
		TriCHK[i]->prot[0],TriCHK[i]->prot[1],TriCHK[i]->prot[2])) {
	   if (Tri->conf == TriCHK[i]->conf) return(1);
	}
   }

   return(0);
}

void Filter_No_Contact(int *iclos)
{
   int i,j,k,l,n,nt,flg,fnd1,fnd2;
   float Cen[3],frac,dmin,dmint;
   float xyz1[3],xyz2[3];

   Cen[0] = BIGD; Cen[1] = BIGD; Cen[2] = BIGD; fnd1 = 0;

   if (debugdck) {
	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) {

		if (TriArr[i]->coo == NULL) continue;

		fnd1 = PrtConf(TriArr[i],i);
		if (fnd1) {
		   fprintf(stderr,"Filter_No_Contact:\n\n\
			++++++++++++++++++++++++\n\
			Found input ligand pose:\n\
			itri [%d] conf %d\n\
			++++++++++++++++++++++++\n\n",
			i,TriArr[i]->conf);
		}
	   }
	}
   }

   fnd2 = 0;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    nt = 0;

	    if (!(TriArr[i]->Cen[0] == Cen[0] &&
		  TriArr[i]->Cen[1] == Cen[1] &&
		  TriArr[i]->Cen[2] == Cen[2])) {
	       for (l=0; l < 3; l++) {
		   Cen[l] = TriArr[i]->Cen[l];
	       }
	       nt = FillOpt(iclos,i);
	    }

	    n = 0;

	    for (k=0; k < ndocka; k++) {
		for (l=0; l < 3; l++) {
		   xyz2[l] = (float) TriArr[i]->coo[k*3+l]*toangs;
		}
		dmin = BIGD;
	    	for (j=0; j < *xyzp->iatoms; j++) {
		    if (iclos[j] == 1) {
			for (l=0; l < 3; l++) {
			   xyz1[l] = (float) xyzp->coo[j*3+l]*toangs;
			}

			dmint = Atom_Distance(xyz1,xyz2);
			if (dmint < dmin) dmin = dmint;
		    }
		}
		if (dmin != BIGD) {
		   if (dmin > DISTOL) n++;
		}
	    }

	    frac = (float) n / (float) ndocka;

	    if (frac > DISFRAC) {
	 	TriCooSafeFree(i);
	   	TriSafeFreeTxt(i,"Filter_No_Contact",
				"Reason: close contact: frac > DISFRAC");
	    }
	}
   }

   Compress_Tri_L();

   if (debugdck) fprintf(stderr,"aft Filter_No_Contact: ntris %d\n",ntris);

}

float Overlap_Spheres(float* xyz1, float* xyz2, float vdwr1, float vdwr2)
{
   int i,j;
   float d,d2,dd,cosa,cost,vdwsum,h1,h2,h12,h22,overl;

   d2 = 0.0;
   for (i=0; i<3; i++) {
	dd = xyz1[i] - xyz2[i];
	d2 = d2 + dd*dd;
   }
   
   d = sqrt(d2);

   if (d > (vdwr1 + vdwr2)) return(0.0);

   vdwsum = vdwr1*vdwr1 - vdwr2*vdwr2;
   cosa = (d2 + vdwsum) / (2.0*vdwr1*d);
   cost = (d2 - vdwsum) / (2.0*vdwr2*d);

   h1 = vdwr1*(1.0 - cosa);
   h2 = vdwr2*(1.0 - cost);

   h12 = h1*h1;
   h22 = h2*h2;

   overl = 3.0*(vdwr1*h12 + vdwr2*h22) - (h12*h1 + h22*h2);

   return(overl);
}

//#define MAXOPTSTP 4
#define MAXOPTSTP 8

float Calc_Energy(coo,q,vdwr,vdwe,ql,vdwrl,vdwel,iclos)
double *coo;
float *q;
float *vdwr;
float *vdwe;
float *ql;
float *vdwrl;
float *vdwel;
int *iclos;
{
   float Einter;

   vdwscal = vdwscal_memory;

   Einter = CalcInter(coo,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel);

   vdwscal = 1.0;

   return(Einter);

}

void Optimise_Energy(int itri,int mode,
float *q,float *vdwr,float *vdwe,
float *ql,float *vdwrl,float *vdwel,int *iclos)
{
   int i,j,k,l,m,n,iener,il0,il1,il2,il3;
   float enermin,ener[MAXOPTSTP];
   double vec1[3],vec2[3],vec3[3],fr;

   if (TriArr[itri] == NULL) return;
   if (TriArr[itri]->coo == NULL) return;

   enermin = BIGD;
   iener = -1;

   il0 = ligtyp[TriArr[itri]->lig[0]]->atom[0];
   il1 = inttyp[TriArr[itri]->prot[0]]->atom[0];

// this vec should now be between ligand atom and protein atom

   if (mode) {

	dvecnrm(vec1);

	for (i=0; i<3; i++) {
	   vec1[i] = xyzp->coo[il1*3+i] - TriArr[itri]->coo[il0*3+i];
	}

	il2 = ligtyp[TriArr[itri]->lig[0]]->atom[0];
	il3 = ligtyp[TriArr[itri]->lig[1]]->atom[0];

	for (i=0; i<3; i++) {
	   vec2[i] = TriArr[itri]->coo[il3*3+i] - TriArr[itri]->coo[il2*3+i];
	}

	dvecnrm(vec2);

	crossprd(vec2,vec1,vec3);

	for (i=0; i<3; i++) {
	   vec1[i] = vec3[i];
	}
   }

   dvecnrm(vec1);

   for (m=0; m<MAXOPTSTP; m++) {

	    fr = (double) m / (double) (MAXOPTSTP-1);

	    for (i=0; i<ndocka; i++) {
		for (j=0; j<3; j++) {
		   DSTxyz.coo[i*3+j] = TriArr[itri]->coo[i*3+j] 
				 + fr*vec1[j];
		}
	    }
	    ener[m] = Calc_Energy(DSTxyz.coo,
		q,vdwr,vdwe,ql,vdwrl,vdwel,iclos);

	    if (ener[m] < enermin) {
		enermin = ener[m];
		iener = m;
	    }
   }

   if (iener != -1) {
	TriArr[itri]->eint = enermin;
	fr = (double) iener / (double) (MAXOPTSTP-1);
	for (i=0; i<ndocka; i++) {
	   for (j=0; j<3; j++) {
		TriArr[itri]->coo[i*3+j] = TriArr[itri]->coo[i*3+j] 
			+ fr*vec1[j];
	   }
	}
	for (j=0; j<3; j++) {
	   TriArr[itri]->p1[j] = TriArr[itri]->p1[j] + fr*vec1[j];
	   TriArr[itri]->p2[j] = TriArr[itri]->p2[j] + fr*vec1[j];
	   TriArr[itri]->p3[j] = TriArr[itri]->p3[j] + fr*vec1[j];
	}
   }


}

void Optimise_Overlap(int itri,
float *vdwr,float *vdwrl)
{
   int i,j,k,l,m,n,iover,il0,il1,nclos;
   float overl,overlmin,over[MAXOPTSTP];
   float xyz1[3],xyz2[3];
   double vec[3],fr;

   overlmin = BIGD;
   iover = -1;

   il0 = ligtyp[TriArr[itri]->lig[0]]->atom[0];
   il1 = ligtyp[TriArr[itri]->lig[1]]->atom[0];

   for (i=0; i<3; i++) {
	vec[i] = TriArr[itri]->coo[il1*3+i] - TriArr[itri]->coo[il0*3+i];
   }

   for (m=0; m<MAXOPTSTP; m++) {

	if (TriArr[itri] != NULL) {

	    if (TriArr[itri]->coo == NULL) continue;

// copy TriArr[itri]->coo to DSTxyz

	    fr = (double) m / (double) (MAXOPTSTP-1);

	    for (i=0; i<ndocka; i++) {
		for (j=0; j<3; j++) {
		   DSTxyz.coo[i*3+j] = TriArr[itri]->coo[i*3+j] 
				 + fr*vec[j];
		}
	    }

	    overl = 0.0;

	    for (j=0; j < *xyzp->iatoms; j++) {
		if (xyzp->iclos[j] == 1) {

		    for (l=0; l < 3; l++) {
			xyz1[l] = (float) (xyzp->coo[j*3+l]*toangs);
		    }

		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++) {
			   xyz2[l] = (float) (DSTxyz.coo[k*3+l]*toangs);
			}
			overl = overl + 
			   Overlap_Spheres(xyz1,xyz2,vdwr[j],vdwrl[k]);
		    }
		}
	    }

	    over[m] = overl/((float) NCLOS);
	    if (over[m] < overlmin) {
		overlmin = over[m];
		iover = m;
	    }
	}
   }

   if (iover != -1) {
	TriArr[itri]->overl = overlmin;
	fr = (double) iover / (double) (MAXOPTSTP-1);
	for (i=0; i<ndocka; i++) {
	   for (j=0; j<3; j++) {
		TriArr[itri]->coo[i*3+j] = TriArr[itri]->coo[i*3+j] 
			+ fr*vec[j];
	   }
	}
	for (j=0; j<3; j++) {
	   TriArr[itri]->p1[j] = TriArr[itri]->p1[j] + fr*vec[j];
	   TriArr[itri]->p2[j] = TriArr[itri]->p2[j] + fr*vec[j];
	   TriArr[itri]->p3[j] = TriArr[itri]->p3[j] + fr*vec[j];
	}
   }

}

void Calc_Overlap2()
{
   int i,j,k,l,n,*iclos;
   int secs;
   float *q,*vdwr,*vdwe,*F,overl,Cen[3];
   float xyz1[3],xyz2[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   double secnds;

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   Cen[0] = BIGD; Cen[1] = BIGD; Cen[2] = BIGD;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    if (!(TriArr[i]->Cen[0] == Cen[0] &&
		  TriArr[i]->Cen[1] == Cen[1] &&
		  TriArr[i]->Cen[2] == Cen[2])) {
	       for (l=0; l < 3; l++) {
		   Cen[l] = TriArr[i]->Cen[l];
	       }

	    }

	    overl = 0.0;

	    for (j=0; j < *xyzp->iatoms; j++) {
		if (xyzp->iclos[j] == 1) {
		    for (l=0; l < 3; l++) {
			xyz1[l] = (float) xyzp->coo[j*3+l]*toangs;
		    }

		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++) {
			   xyz2[l] = (float) TriArr[i]->coo[k*3+l]*toangs;
			}
			overl = overl + 
			   Overlap_Spheres(xyz1,xyz2,vdwr[j],vdwrl[k]);
		    }
		}
	    }
	    TriArr[i]->overl = overl/((float) NCLOS);
	}
   }

   if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpover);
   }

   free(vdwr);
   free(vdwe);
   free(q);
   free(iclos);

   if (strcmp(pdbcode,"3k3e") == 0) {
	DelTriNOT(20,14,0,151,150,160,0);
//	identify(20,14,0,151,150,160);
   }

   if (nglut > 0) {
	for (i = 0; i < nglut; i++) {
	   for (j = 0; j < nnhp; j++) {
		for (k = 0; k < nco; k++) {
		   identify(ANHP[j],ACO[k],0,GLUTCO[i],GLUTH[i],160);
		}
	   }
	}
   }

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) PrtTrp(i);
   }

/*
   n = -1;
   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->overl > 1.8 && n == -1) n = i;
	}
   }

   if (n != -1) {
	for (i=n; i < ntris; i++) {
	   if (TriArr[i] != NULL) {
		TriCooSafeFree(i);
		TriSafeFreeTxt(i,"Calc_overlap2","Reason: only entries with overl <= 2.0");
	   }
	}
	ntris = n;
   }

   Compress_Tri_L();
*/

//   if (debugdck) Write_Results("affltdis.mol2",TriArr,n,&DCKxyz,2,0);
   if (debugdck) Write_Results("affltdis.mol2",TriArr,ntris,&DCKxyz,2,0);

   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"affltdis took:\n\n");
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}

void Calc_Overlap()
{
   int i,j,k,l,n,*iclos;
   float *q,*vdwr,*vdwe,*F,overl,Cen[3];
   float xyz1[3],xyz2[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   Cen[0] = BIGD; Cen[1] = BIGD; Cen[2] = BIGD;

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    if (!(TriArr[i]->Cen[0] == Cen[0] &&
		  TriArr[i]->Cen[1] == Cen[1] &&
		  TriArr[i]->Cen[2] == Cen[2])) {
	       for (l=0; l < 3; l++) {
		   Cen[l] = TriArr[i]->Cen[l];
	       }
	       if (DCKMETH == 0) {
		 n = FillOptD(iclos);
	       } else {
		 n = FillOpt(iclos,i);
	       }

	    }

	    overl = 0.0;

	    for (j=0; j < *xyzp->iatoms; j++) {
		if (iclos[j] == 1) {
		    for (l=0; l < 3; l++) {
			xyz1[l] = (float) xyzp->coo[j*3+l]*toangs;
		    }

		    for (k=0; k < ndocka; k++) {
			for (l=0; l < 3; l++) {
			   xyz2[l] = (float) TriArr[i]->coo[k*3+l]*toangs;
			}
			overl = overl + 
			   Overlap_Spheres(xyz1,xyz2,vdwr[j],vdwrl[k]);
		    }
		}
	    }
	    TriArr[i]->overl = overl/((float) n);
	}
   }

   if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpover);
   }

   Filter_No_Contact(iclos);

   Compress_Tri_L();

   n = MINI(1000,ntris);

   if (debugdck) Write_Results("affltdis.mol2",TriArr,n,&DCKxyz,2,0);

   free(vdwr);
   free(vdwe);
   free(q);
   free(iclos);
}

int RemLoops(int j,int all,double CLOSED,int *ipdb,int *ihpdb)
{
   int i,k,l,ido;
   float tt,dd;
   double ddd,ttd;

   for (i=0; i<MXSYM; i++) {
	if (ipdb[i] > 0) {
	    for (k = 0; k < ndocka; k++ ) {

		ido = 0;
		if (!all) {
		   if (TriArr[j]->conf == -1) {
			if (singleb.ifrg[k] == TriArr[j]->frag) ido = 1;
		   } else {
			if (singleb.ifrg[k] == TriArr[j]->frags[0] ||
	    		    singleb.ifrg[k] == TriArr[j]->frags[1] ||
	    		    singleb.ifrg[k] == TriArr[j]->frags[2]) ido = 1;
		   }
		} else {
			ido = 1;
		}

		if (ido) {
		   ddd = 0.0;
		   if (TriArr[j]->coo != NULL) {
		      for (l = 0; l < 3; l++ ) {
			ttd = xyzp->coo[(ipdb[i]-1)*3+l] - 
				TriArr[j]->coo[k*3+l];
			ddd = ddd + ttd*ttd;
		      }
		      if (sqrt(ddd) < CLOSED) return(1);
		   }
		}

	    } // end for k ndocka
	} // ifend ipdb[i] > 0
   } // end for i MXSYM

   for (i=0; i<3*MXHSYM; i++) {
	if (ihpdb[i] > 0) {
	    for (k = 0; k < ndocka; k++ ) {
		ido = 0;
		if (!all) {
		   if (TriArr[j]->conf == -1) {
			if (singleb.ifrg[k] == TriArr[j]->frag) ido = 1;
		   } else {
			if (singleb.ifrg[k] == TriArr[j]->frags[0] ||
	    		    singleb.ifrg[k] == TriArr[j]->frags[1] ||
	    		    singleb.ifrg[k] == TriArr[j]->frags[2]) ido = 1;
		   }
		} else {
		   ido = 1;
		}

		if (ido) {

		   if (TriArr[j]->coo != NULL) {
		      ddd = 0.0;
		      for (l = 0; l < 3; l++ ) {
			ttd = xyzp->coo[(ihpdb[i]-1)*3+l] - 
				TriArr[j]->coo[k*3+l];
			ddd = ddd + ttd*ttd;
		      }

		      if (sqrt(ddd) < CLOSED) return(1);
		   }
		}

	    } // end for k ndocka
	} // if end ihpdb[i] > 0
   } // end for i = MXHSYM

   return(0);
}

void RemCC_All(int all)
{
    int j,ires;
    double CLOSED;

    CLOSED = CLOSEC/toangs;

    if (*ipdbon && calfptr->ncalf != 0) {
	for (ires = 1; ires < calfptr->ncalf+1; ires++ ) {

   	   getpdb_(&ires,ipdb,ihpdb);

	   for (j = 0; j < ntris; j++ ) {
		if (TriArr[j] != NULL) {

		   if (RemLoops(j,all,CLOSED,ipdb,ihpdb)) TriCooSafeFree(j);
		   
		} // if end TriArr[j] != NULL
	   } // end for j ntris


	}
    }

    Compress_Tri_L();

}

int ChkAro(ia1,ia2,xyz)
int ia1;
int ia2;
COOSTRU *xyz;
{
   int i,j,k,n1,n2,ian,ian1,ian2,ian3,ian12,ian13,ian23,itel;
   int ica1,ica2,icn[3];

   n1 = xyz->iconn[ia1*(MXCON+1)];
   n2 = xyz->iconn[ia2*(MXCON+1)];

   itel = 0;

   for (j=0; j < n1; j++) {
	k = xyz->iconn[ia1*(MXCON+1)+j+1];
	k = ABS(k) - 1;
	if (k != ia2 && itel < 3) {
	   icn[itel] = k;
	   itel++;
	}
   }

   ica1 = 0;

   if (itel == 2) {
	if (singleb.irsd[icn[0]] == 4) ica1++;
	if (singleb.irsd[icn[1]] == 4) ica1++;
	if (singleb.irsd[ia1] == 4) ica1++;
   }

   itel = 0;
   for (j=0; j < n2; j++) {
	k = xyz->iconn[ia2*(MXCON+1)+j+1];
	k = ABS(k) - 1;
	if (k != ia1 && itel < 3) {
	   icn[itel] = k;
	   itel++;
	}
   }

   ica2 = 0;

   if (itel == 2) {
	if (singleb.irsd[icn[0]] == 4) ica2++;
	if (singleb.irsd[icn[1]] == 4) ica2++;
	if (singleb.irsd[ia2] == 4) ica2++;
	if ( (ica1 == 3 && ica2 == 2) || (ica1 == 2 && ica2 == 3) ) return(0);
	if (ica1 == 3 && ica2 == 3) return(1);
   }

   return(0);
}

int IsPlanar(i1,i2,i3,i4,xyz)
int i1;
int i2;
int i3;
int i4;
COOSTRU *xyz;
{
   int j;
   float v1[3],v2[3],v3[3],v4[3],v5[3];
   double cosa;

   for (j=0; j<3; j++) {
	v1[j] = xyz->coo[i2*3+j] - xyz->coo[i1*3+j];
	v2[j] = xyz->coo[i3*3+j] - xyz->coo[i1*3+j];
	v3[j] = xyz->coo[i4*3+j] - xyz->coo[i1*3+j];
   }

   cross(v1,v2,v4);
   inprod(v4,v3,&cosa);

   if (fabs(cosa) < 0.3) return(1);

   return(0);
}

int IsNPlanarH2(ia1,ia2,xyz)
int ia1;
int ia2;
COOSTRU *xyz;
{
   int j,k,n1,n2,ian1,ian2,itel;
   int ica1,ica2,icn[3],pl;

   n1 = xyz->iconn[ia1*(MXCON+1)];

   itel = 0;
   ian1 = 0;
   ian2 = 0;

   for (j=0; j < n1; j++) {
	k = xyz->iconn[ia1*(MXCON+1)+j+1];
	k = ABS(k) - 1;
	if (k != ia2 && itel < 3) {
	   icn[itel] = k;
	   itel++;
	}
   }

   pl = 0;

   if (itel == 2) {
	ian1 = xyz->ianz[icn[0]];
	ian2 = xyz->ianz[icn[1]];
	pl = IsPlanar(ia1,icn[0],icn[1],ia2,xyz);
	
   }
 
   if (pl == 1 && ian1+ian2 == 2) return(0);
   return(1);
}

int IsSymFrg(isng,xyz)
int isng;
COOSTRU *xyz;
{
//
// IsSymFRG basically determines the number of conformers
// associated with single bond isng
//
   int i,j,k,n1,n2,ia1,ia2,ian,ian1,ian2,ian3,ian12,ian13,ian23,itel;
   int ica1,ica2,icn[3],pl1,pl2;

   ia1 = singleb.sng[isng][0];
   ia2 = singleb.sng[isng][1];

   n1 = xyz->iconn[ia1*(MXCON+1)];
   n2 = xyz->iconn[ia2*(MXCON+1)];

   itel = 0;

   for (j=0; j < n1; j++) {
	k = xyz->iconn[ia1*(MXCON+1)+j+1];
	k = ABS(k) - 1;
	if (k != ia2 && itel < 3) {
	   icn[itel] = k;
	   itel++;
	}
   }

   pl1 = 0;
   ica1 = 0;

   switch(itel) {
   case 3:
	ian1 = xyz->ianz[icn[0]];
	ian2 = xyz->ianz[icn[1]];
	ian3 = xyz->ianz[icn[2]];
	break;
   case 2:
	ian1 = xyz->ianz[icn[0]];
	ian2 = xyz->ianz[icn[1]];
	ian3 = 0;
	if (singleb.irsd[icn[0]] == 4) ica1++;
	if (singleb.irsd[icn[1]] == 4) ica1++;
	if (singleb.irsd[ia1] == 4) ica1++;
	pl1 = IsPlanar(ia1,icn[0],icn[1],ia2,xyz);
	break;
   case 1:
	ian1 = xyz->ianz[icn[0]];
	ian2 = 0;
	ian3 = 0;
	break;
   case 0:
	ian1 = 0;
	ian2 = 0;
	ian3 = 0;
	break;
   default:
	break;
   }

   ian12 = ian1 + ian2;
   ian13 = ian1 + ian3;
   ian23 = ian2 + ian3;

   if (itel == 3) {
	if (ian1 == ian2 && ian1 == ian3) return(1);
	if (ian12 == 2 || ian13 == 2 || ian23 == 2) return(2);
   }

   itel = 0;
   for (j=0; j < n2; j++) {
	k = xyz->iconn[ia2*(MXCON+1)+j+1];
	k = ABS(k) - 1;
	if (k != ia1 && itel < 3) {
	   icn[itel] = k;
	   itel++;
	}
   }

   pl2 = 0;
   ica2 = 0;

   switch(itel) {
   case 3:
	ian1 = xyz->ianz[icn[0]];
	ian2 = xyz->ianz[icn[1]];
	ian3 = xyz->ianz[icn[2]];
	break;
   case 2:
	ian1 = xyz->ianz[icn[0]];
	ian2 = xyz->ianz[icn[1]];
	ian3 = 0;
	if (singleb.irsd[icn[0]] == 4) ica2++;
	if (singleb.irsd[icn[1]] == 4) ica2++;
	if (singleb.irsd[ia2] == 4) ica2++;
	pl2 = IsPlanar(ia2,icn[0],icn[1],ia1,xyz);
	break;
   case 1:
	ian1 = xyz->ianz[icn[0]];
	ian2 = 0;
	ian3 = 0;
	break;
   case 0:
	ian1 = 0;
	ian2 = 0;
	ian3 = 0;
	break;
   default:
	break;
   }

   ian12 = ian1 + ian2;
   ian13 = ian1 + ian3;
   ian23 = ian2 + ian3;

   if (itel == 3) {
	if ((xyz->ianz[ia1] == 16 || xyz->ianz[ia2] == 16) && 
	   (ian1 == ian2 && ian1 == ian3)) return(3);
//	   (ian1 == ian2 && ian1 == ian3)) return(2);
	if (ian1 == ian2 && ian1 == ian3) return(1);
	if (pl1 == 1 && ica1 == 3) return(4);
	if (pl2 == 1 && ica2 == 3) return(4);
	if (ian12 == 2 || ian13 == 2 || ian23) return(2);
   } else if (itel == 2) {
	if (pl1 == 1 && ica1 == 3) return(4);
	if (pl2 == 1 && ica2 == 3) return(4);
	if (ica1 == 3 && ica2 == 3) return(2);
	if (pl1 == 1 && pl2 == 1) return(2);
   }

   return(3);
}

int ChkSng(int ia1, int ia2)
{
   int i;

   for (i=0; i < singleb.N; i++) {
	if (singleb.sng[i][0] == ia1 &&
	    singleb.sng[i][1] == ia2) return(1);
   }
   return(0);
}

int CMPSng()
{
   int i;

   for (i = 0; i < singleb.N; i++) {
	if (singleb.sng[i][0] == singleb.sng[singleb.N][0] &&
	    singleb.sng[i][1] == singleb.sng[singleb.N][1]) return(0);
	if (singleb.sng[i][0] == singleb.sng[singleb.N][1] &&
	    singleb.sng[i][1] == singleb.sng[singleb.N][0]) return(0);
   }
   return(1);
}

void ExtraFrag(C)
COOSTRU *C;
{

   int i,in,j,k[3],kn,ktot,krng,ir1,ir2,iflg1,iflg2;
   int reor[MXLIGA],sng[MXLIGA][2],jmin,kmin,ktel;

   for (i=0; i < ndocka; i++) {

	in = C->iconn[i*(MXCON+1)];
	ir1 = singleb.jrng[i];
	iflg1 = 0;
	krng = -1;
	
	if (in == 3 && ir1) {
	   ktot = 0;
	   for (j=0; j < 3; j++) {
		k[j] = C->iconn[i*(MXCON+1)+j+1]-1;
		if (singleb.jrng[k[j]] == ir1) {
		   ktot++;
		} else {
		   krng = k[j];
		}
	   }

	   if (ktot == 2) iflg1 = 1;
	}

	if (iflg1 && krng != -1 && krng > i) {

	   kn = C->iconn[krng*(MXCON+1)];
	   ir2 = singleb.jrng[krng];
	   iflg2 = 0;

	   if (kn == 3 && ir2) {

		ktot = 0;
		for (j=0; j < 3; j++) {
		   k[j] = C->iconn[krng*(MXCON+1)+j+1]-1;
		   if (singleb.jrng[k[j]] == ir2) ktot++;
	   	}

		if (ktot == 2) iflg2 = 1;
	   }

	   if (iflg2) {
		if (!ChkSng(i,krng)) {
		   singleb.sng[singleb.N][0] = i;
		   singleb.sng[singleb.N][1] = krng;
		   if (CMPSng()) singleb.N++;
		}
	   }

	}
	
	if (iflg1 && krng != -1 && krng < ndocka) {

	   kn = C->iconn[krng*(MXCON+1)];
	   ir2 = singleb.irsd[krng];
	   iflg2 = 0;

	   if (kn == 3 && ir2 == 2) iflg2 = 1;


	   if (iflg2) {
		if (!ChkSng(i,krng)) {
		   singleb.sng[singleb.N][0] = i;
		   singleb.sng[singleb.N][1] = krng;
		   if (CMPSng()) singleb.N++;
		}
	   }
	}
   }

}

void Fragmentise(xyz)
COOSTRU *xyz;
{
   int i,j,k,l,n,m,itel,icn[4*MXCON],ICN[4*MXCON],N,iflg;

   singleb.NFRAG = 0;

   for (i=0; i < ndocka; i++) {
	singleb.ifrg[i] = -1;
   }

   singleb.ifrg[0] = 0;
   N = 1;
   ICN[0] = 0;

   while (1) {

      n = 0;

      for (m=0; m < N; m++) {

	i = ICN[m];
	singleb.ifrg[i] = singleb.NFRAG;

	for (j=0; j < xyz->iconn[i*(MXCON+1)]; j++) {

	   k = xyz->iconn[i*(MXCON+1)+j+1];
	   k = ABS(k) - 1;

	   if (singleb.ifrg[k] == -1) {

		iflg = 0;

		for (l=0; l < singleb.N; l++) {
		   if (singleb.sng[l][0] == i && singleb.sng[l][1] == k) {
			iflg = 1;
		   }
		   if (singleb.sng[l][0] == k && singleb.sng[l][1] == i) {
			iflg = 1;
		   }
		}

		if (!iflg)  {
		   singleb.ifrg[k] = singleb.NFRAG;
		   icn[n] = k;
		   n++;
		}
	   }
	}
      }

      N = n;

      for (l=0; l < N; l++) {
	ICN[l] = icn[l];
      }


      if (!N) {

	iflg = 1;

        for (l=0; l < ndocka; l++) {
	   if (singleb.ifrg[l] == -1) {
		iflg = 0;
		ICN[0] = l;
		N = 1;
		singleb.NFRAG++;
		break;
	   }
	}
	if (iflg) break;
      }

   }

   singleb.NFRAG++;

   
   for (i=0; i < singleb.N; i++) {
	singleb.SngFrg[i][0] = singleb.ifrg[singleb.sng[i][0]];
	singleb.SngFrg[i][1] = singleb.ifrg[singleb.sng[i][1]];
	singleb.sngdone[i] = 0;
   }

   for (i=0; i < singleb.NFRAG; i++) {

	itel = 0;

	for (j=0; j < singleb.N; j++) {
	   if (i == singleb.ifrg[singleb.sng[j][0]] ||
	       i == singleb.ifrg[singleb.sng[j][1]]) {
		singleb.FrgSng[i][itel] = j;
		itel++;
	   }

	   singleb.FrgSngN[i] = itel;
	}
   }

}

void Map_Conformers(int opt)
{
   int i,j,k,l,ntrism1,beg[MAXTRI],end[MAXTRI],at1,at2,at3;
   int size,doflip[3],in;
   float Emin;
   double d,dmin;
    
   in = -1; dmin = BIGD;

   size = MXLIGA;
   alldck(&DCKtmp,&size);

   TriAll(&TriArr[100]);

if (ntriS > MAXTRI) fprintf(stderr,"ntriS %d > MAXTRI %d\n",ntriS,MAXTRI);

   for (i=0; i < ntriS; i++) {
	beg[i] = -1;
	end[i] = -1;
   }

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	  if (TriArr[i]->coo != NULL) {

	    if (TriArr[i]->triS < MAXTRI && TriArr[i]->triS >= 0) {
		if (beg[TriArr[i]->triS] == -1) {
		   beg[TriArr[i]->triS] = i;
		}
		end[TriArr[i]->triS] = i;
	    }

	  }
	}
   }


   for (i=0; i < ntriS; i++) {

	Tri1.grp[0] = TriS[i].grp[0];
	Tri1.grp[1] = TriS[i].grp[1];
	Tri1.grp[2] = TriS[i].grp[2];
	Tri1.frag   = TriS[i].frag;

	Tri2.grp[0] = TriS[i].grp[0];
	Tri2.grp[1] = TriS[i].grp[1];
	Tri2.grp[2] = TriS[i].grp[2];
	Tri2.lig[0] = TriS[i].lig[0];
	Tri2.lig[1] = TriS[i].lig[1];
	Tri2.lig[2] = TriS[i].lig[2];
	Tri2.ohlig[0] = TriS[i].ohlig[0];
	Tri2.ohlig[1] = TriS[i].ohlig[1];
	Tri2.ohlig[2] = TriS[i].ohlig[2];
	Tri2.frag   = TriS[i].frag;

	at1 = TriS[i].atindx[0];
	at2 = TriS[i].atindx[1];
	at3 = TriS[i].atindx[2];

	if (beg[i] != -1 && end[i] != -1) {

	   for (j=beg[i]; j < end[i]+1; j++) {

	    if (TriArr[j] != NULL && TriFin[k] != NULL) {

		if (TriArr[j]->coo == NULL || TriFin[k]->coo == NULL) continue;

		for (l=0; l < 3; l++) {
		   Tri1.p1[l] = TriArr[j]->coo[at1*3+l];
		   Tri1.p2[l] = TriArr[j]->coo[at2*3+l];
		   Tri1.p3[l] = TriArr[j]->coo[at3*3+l];
	   	}

	   	Calc_Centroid(&Tri1);

	   	for (k=0; k < ntrif; k++) {

	    	 if (TriFin[k] != NULL) {

		   for (l=0; l < 3; l++) {
			Tri2.p1[l] = TriFin[k]->coo[at1*3+l];
			Tri2.p2[l] = TriFin[k]->coo[at2*3+l];
			Tri2.p3[l] = TriFin[k]->coo[at3*3+l];
		   }

// allocate new triarr structure, set TriA to TriArr original coo

		   ntris++;
		   if (ntris >= MAXTRI) {
			ntris = MAXTRI - 1;
			return;
		   }
		   ntrism1 = ntris-1;

	   	   TriAll(&TriArr[ntrism1]);

		   for (l=0; l < 3; l++) {
			TriArr[ntrism1]->p1[l]  = Tri2.p1[l];
			TriArr[ntrism1]->p2[l]  = Tri2.p2[l];
			TriArr[ntrism1]->p3[l]  = Tri2.p3[l];
			TriArr[ntrism1]->grp[l] = Tri2.grp[l];
			TriArr[ntrism1]->lig[l] = Tri2.lig[l];
			TriArr[ntrism1]->ohlig[l] = Tri2.ohlig[l];
			TriArr[ntrism1]->prot[l] = TriArr[j]->prot[l];
		   }

		   TriArr[ntrism1]->conf = k;

		   Calc_Centroid(TriArr[ntrism1]);

		   Trans_Tri(&Tri1,TriArr[ntrism1],opt);
		   if (opt) {
		      for (l=0;l<3;l++) {
			TriArr[ntrism1]->lig[l] = Tri2.lig[l];
			TriArr[ntrism1]->ohlig[l] = Tri2.ohlig[l];
			TriArr[ntrism1]->prot[l] = TriArr[j]->prot[l];
		      }
	 	   }
		   Copy_OH(TriFin[k]->coo,DCKtmp.coo,
			TriArr[ntrism1]->lig[0],TriArr[ntrism1]->lig[1],
			TriArr[ntrism1]->lig[2],
			doflip[0],doflip[1],doflip[2]);
		   Trans_Coo(TriArr[ntrism1],DCKtmp.coo);

		   TriArr[ntrism1]->frag = Tri2.frag;
		   TriArr[ntrism1]->eint = TriArr[j]->eint + TriFin[k]->eint;
		   TriArr[ntrism1]->e12  = TriArr[j]->e12;
		   TriArr[ntrism1]->spec  = TriArr[j]->spec;
		   TriArr[ntrism1]->itry  = TriArr[j]->itry;

		   for (l=0; l < 3; l++) {
			TriArr[ntrism1]->Cen[l] = TriArr[j]->Cen[l];
			TriArr[ntrism1]->ohlig[l] = TriArr[j]->ohlig[l];
			TriArr[ntrism1]->prot[l] = TriArr[j]->prot[l];
		   }

		 }
		}

		if (TriArr[j] != NULL) {
		   if (TriArr[j]->coo != NULL) {
	        	TriCooSafeFree(j);
			TriArr[j]->coo = NULL;
		   }

	   	   TriSafeFreeTxt(j,"Map_Conformers",
				"Reason: remove original triangle");
		}
	    }

	   }
	}
   }

   if (!e12_calculated) CalcAllInt(0,1);

   if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpe12);
   }

   Emin = BIGD;
   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		if (TriArr[i]->e12 < Emin) Emin = TriArr[i]->e12;
	   }
	}
   }

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   if (TriArr[i]->coo != NULL) {
		if (TriArr[i]->e12 > Emin + E12WIN) {
		   TriArr[i]->coo = NULL;
		}
	   }
	}
   }

   Compress_Tri_L();

   if (debugdck) Write_Results("Map_Conformers.mol2",TriArr,ntris,&DCKxyz,0,0);
}

// Map_Conformers uses existing array of TriArr
// to create new array elements with new conformers. However, these add
// the original conformer, so we need to remove the original.

double OriDist(double *coo1, double *coo2)
{
   int i,j;
   double tt,total;

   tt = 0.0;
   total = 0.0;

   for (i=0; i < 3; i++) {
	tt = coo1[i]*toangs - coo2[i]*toangs;
	tt = tt*tt;
	total = total + tt;
   }

   total = sqrt(total);

   return(total);
}

void SetLTYP()
{
   int i,j,CARR[MXCONFARR];

   for (i=0; i < lintp; i++) {
     if (ligtyp[i] != NULL) {
 	ligtyp[i]->nconf = 1;	
	CARR[0] = ligtyp[i]->conf;
	for (j=i+1; j < lintp; j++) {
	   if (j < MAXLIGSTRU) {
		if (ligtyp[i] != NULL && ligtyp[j] != NULL) {
		  if (!struct_cmp(&ligtyp[i]->area,&ligtyp[j]->area)) {
		   if ( (ligtyp[i]->ORI[0] == ligtyp[j]->ORI[0]) &&
			(ligtyp[i]->ORI[1] == ligtyp[j]->ORI[1]) &&
			(ligtyp[i]->ORI[2] == ligtyp[j]->ORI[2]) ) {
			if (ligtyp[i]->nconf < MXCONFARR) {
			   CARR[ligtyp[i]->nconf] = ligtyp[j]->conf;
			   ligtyp[i]->nconf++;
			   safefree((void **)&ligtyp[j]);
			   ligtyp[j] = NULL;
			}
		   }
		  }
		}
	   }
	}
	if (ligtyp[i]->nconf > 0 && ligtyp[i]->ConfArr == NULL) {
           ligtyp[i]->ConfArr = (int *) malloc(ligtyp[i]->nconf*sizeof(int));
           for (j=0; j < ligtyp[i]->nconf; j++) {
                ligtyp[i]->ConfArr[j] = CARR[j];
	}
     }

    }

   }
}

void Compress_Ligtyp_List()
{
   int i,j,k,lint,CARR[MXCONFARR];

   for (i=0; i < lintconf; i++) {
      ligtyp[i]->ConfArr = NULL;
   }

   SetLTYP();

   lint = 0;
   for (i=0; i < lintp; i++) {
	if (ligtyp[i] != NULL) {
	   if (i != 0) {
		ligtyp[lint] = ligtyp[i];
		lind[i] = lint;
	   }
	   lint++;
	}
   }

   lintp = lint;

}

void AssLig(C,coo,iconf)
COOSTRU *C;
double *coo;
int iconf;
{
// AssLig creates interaction points from ligand OR
// ligand conformers, through coo's generated for conformers 

   int i,i1,in,iret,indx,indxm,it,j,k,kn,l,ll,m,n,noh,nring,pl,kc1,kc2,jj;
   int jm1,jp1,io1,io2,io3,con1,con2;
   int aro,c2ar,n2ar,n2art,n2d,s2,ivalr,isetconf;
   int iring[6],oring[6],iele[4];
   double c1[3],c2[3],v1[3];

   ivalr = 0; 
   isetconf = 0;

   if (lintp == 0) isetconf = 1;

   singleb.extra = 0;

   for (i=0; i < ndocka; i++) {
	singleb.irng[i] = 0;
	singleb.ring[i] = 0;
	singleb.jrng[i] = 0;
	C->lring[i] = 0;
	C->lwrit[i] = 0;
	C->iaton[i] = 2;
   }

   for (i=0; i < ndocka; i++) {
	i1 = i + 1;
	nring = 0;
	ringd_(&i1,iring,&nring,&ZERO,
	C->ianz,C->iaton,C->iconn,C->lwrit,C->lring, &iret);

	if (iret == 1) {
	   if (nring == 6 || nring == 5) singleb.irng[i] = 1;
	}
   }

   for (i=0; i < ndocka; i++) {
	C->lring[i] = 0;
	C->lwrit[i] = 0;
	C->iaton[i] = 2;
   }

   for (i=0; i < ndocka; i++) {

	i1 = i + 1;
	in = C->iconn[i*(MXCON+1)];
	
	for (j=0; j < in; j++) {
	   k = C->iconn[i*(MXCON+1)+j+1]-1;
	   kn = C->iconn[k*(MXCON+1)];
	   if (k >= 0) {
		if (k > i && (kn != 1 && in != 1)) {
		   if (singleb.irsd[i] == 3 || singleb.irsd[k] == 3) {
			pl = 1;
			if (C->ianz[i] == 8 || C->ianz[k] == 8) {
			   if (C->ianz[i] == 8 && C->ianz[k] == 1) pl = 0;
			   if (C->ianz[k] == 8 && kn == 2) {
				kc1 = C->iconn[k*(MXCON+1)+1]-1;
				kc2 = C->iconn[k*(MXCON+1)+2]-1;
				if (C->ianz[kc1] == 1 || C->ianz[kc2] == 1) 
					pl = 0;
			   }
			} if (C->ianz[i] == 7) {
			   pl = IsNPlanarH2(i,k,C);
			} else if (C->ianz[k] == 7) {
			   pl = IsNPlanarH2(k,i,C);
			}

			con1 = !(ABS(singleb.ityp[i]) == 36 && 
					ABS(singleb.ityp[k]) == 2);
			con2 = !(ABS(singleb.ityp[i]) == 2 && 
					ABS(singleb.ityp[k]) == 36);
			if (pl && con1 && con2) {
			   if ((!singleb.irng[i] || !singleb.irng[k]) ||
			       (ABS(singleb.ityp[i])  == 50 || 
					!singleb.irng[k]) ) {
				singleb.sng[singleb.N][0] = i;
				singleb.sng[singleb.N][1] = k;
				if (singleb.N < MXLIGA) {
				   if (CMPSng()) singleb.N++;
				}
			   }
			}
		   } // if (singleb.irsd[i] == 3 || singleb.irsd[k] == 3)

		   if ((ABS(singleb.ityp[i]) == 2 && C->ianz[k] != 7) ||
			(ABS(singleb.ityp[k]) == 2 && C->ianz[i] != 7)) {
			   singleb.sng[singleb.N][0] = i;
			   singleb.sng[singleb.N][1] = k;
			   if (CMPSng()) singleb.N++;
		   }
		
		   if (singleb.irsd[i] == 4 && singleb.irsd[k] == 4) {
			if (ChkAro(i,k,C)) {
			   singleb.sng[singleb.N][0] = i;
			   singleb.sng[singleb.N][1] = k;
			   if (CMPSng()) singleb.N++;
			}
		   }
		}
	   } //if (k >= 0) {
	} // for (j=0; j < in; j++) {

	nring = 0;
	ivalr++;
	ringd_(&i1,iring,&nring,&ZERO,
	C->ianz,C->iaton,C->iconn,C->lwrit,C->lring, &iret);

	if (iret == 1) {
	   if (nring == 6 || nring == 5) {
		RNGmin1(iring,nring);
		ReORNG(C,iring,nring);
		RNGput(iring,nring,ivalr);
                isC3RNG(C,iring,oring,nring);
		n2ar = 0;
		n2art = -1;
		c2ar = 0;
		aro = 0;
		n2d = 0;
		s2  = 0;
		for (j=0; j < nring; j++) {
		   if (C->ityp[iring[j]] == 23) s2++;
		   if (isANY(C->ityp[iring[j]],C2ar,2)) c2ar++;
		   if (isANY(C->ityp[iring[j]],Aany,6)) aro++;
		   if (isANY(C->ityp[iring[j]],N2ar,2)) {
			if (n2art == -1) {
			   n2art = j;
			} else {
			   n2d = j - n2art;
			}
			n2ar++;
		   }
		}
/* address: ARO = C@AR + N2AR + S.2 */

		if (c2ar == 6 || (c2ar == 5 && n2ar == 1) || 
		   (n2ar == 2 && c2ar == 4) || (n2ar == 3 && c2ar == 3)) {
/* phenyl_center */

		 if (singleb.ring[i] == 0) {
		   AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			3,PHENYL_CENTER,PHC1,coo,iconf,-1);
		   AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			3,PHENYL_CENTER,PHC2,coo,iconf,-1);
		   for (j=0; j < nring; j++) {
			if (oring[j] == 1) {
			   jm1 = j-1; if (jm1 < 0) jm1 = nring-1;
			   jp1 = j+1; if (jp1 > nring-1) jp1 = 0;
			   AllInt(C,&lintp,iring[j],iring[jm1],iring[jp1],
				0,3,PHENYL_RING,PHR,coo,iconf,-1);
			}
			singleb.ring[iring[j]] = 1;
			C->lwrit[iring[j]] = 1;
			if (!FASTSLOW && (HAS_SPEC == 0 && EXTRA_IP == 1)) {
		         if (singleb.extra == 0) {
			   AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			     3,PHENYL_CENTER,PHC1,coo,iconf,-1);
			   for (l=0;l<3;l++) {
				c1[l] = C->coo[iring[0]*3+l];
				c2[l] = C->coo[iring[j]*3+l];
				v1[l] = c2[l] - c1[l];
				ligtyp[lintp-1]->c[0][l] = C->coo[iring[j]*3+l];
				ligtyp[lintp-1]->ORI[l] = C->coo[iring[j]*3+l];
			   }
			   for (l=0;l<ligtyp[lintp-1]->npts; l++ ) {
			      for (m=0;m<3; m++ ) {
				ligtyp[lintp-1]->points[l*3+m] =
				v1[m] + ligtyp[lintp-1]->points[l*3+m];
			      }
			   }
		           AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			     3,PHENYL_CENTER,PHC2,coo,iconf,-1);
			   for (l=0;l<3;l++) {
				c1[l] = C->coo[iring[0]*3+l];
				c2[l] = C->coo[iring[j]*3+l];
				v1[l] = c2[l] - c1[l];
				ligtyp[lintp-1]->c[0][l] = C->coo[iring[j]*3+l];
				ligtyp[lintp-1]->ORI[l] = C->coo[iring[j]*3+l];
			   }
			   for (l=0;l<ligtyp[lintp-1]->npts; l++ ) {
			      for (m=0;m<3; m++ ) {
				ligtyp[lintp-1]->points[l*3+m] =
				v1[m] + ligtyp[lintp-1]->points[l*3+m];
			      }
			   }
			 }
			}
		   }
		   singleb.extra = 1;
		  }
		}

		if ((n2ar == 1 && c2ar == 4) || (n2ar == 2 && c2ar == 3) ||
		    (c2ar == 4 && s2 == 1) ) {
/* phenyl_center */
		 if (singleb.ring[i] == 0) {
		   AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			3,PHENYL_CENTER,PHC1,coo,iconf,-1);
		   AllInt(C,&lintp,iring[0],iring[3],iring[1],0,
			3,PHENYL_CENTER,PHC2,coo,iconf,-1);
		   for (j=0; j < nring; j++) {
			if (oring[j] == 1) {
			   jm1 = j-1; if (jm1 < 0) jm1 = nring-1;
			   jp1 = j+1; if (jp1 > nring-1) jp1 = 0;
			   AllInt(C,&lintp,iring[j],iring[jm1],iring[jp1],
				0,3,PHENYL_RING,PHR,coo,iconf,-1);
			}
			singleb.ring[iring[j]] = 1;
			C->lwrit[iring[j]] = 1;
		   }
		 }
		}

		if (nring == 6) {
		   if (c2ar == 1 && aro == 5) {
			   fprintf(stderr,"adding phenyl ring\n");
/* aro_ring6_H */
		   }
		}
	        singleb.irng[i] = 1;
	   }
	}

	if (isANY(C->ityp[i],Nany,7) && Has_Con(C,i,1,iele) && 
		C->qat[i] >= 0.3) {

	   AllInt(C,&lintp,iele[0],i,0,0,2,H_DON,ONH,coo,iconf,-1);

	} else if (isDON(C->ityp[i]) && Has_Con(C,i,1,iele)) {

	   if (isCOH(i,&io1,&io2,&io3,&it)) {
	      double *GenOH = NULL;

	      if (it == 5) {
		noh = 3;
	        OHGenRot(coo,&GenOH,io1,i,io2,noh,120);
	      } else {
		noh = 2;
		OHGenRot(coo,&GenOH,io1,i,io2,noh,180);
	      }
	      for (jj=0; jj < noh; jj++) {
		if (jj == 0) {
		   OHAllInt(C,&lintp,io2,i,io1,io3,coo,&GenOH[0],iconf,i,-i1,jj);
		} else {
		   OHAllInt(C,&lintp,io2,i,io1,io3,coo,&GenOH[0],iconf,i,i1,jj);
		}
	      }
	   } else {
	      AllInt(C,&lintp,iele[0],i,0,0,2,H_DON,NHP,coo,iconf,-1);
	   }
	   if (iele[1] != -1) {
		AllInt(C,&lintp,iele[1],i,0,0,2,H_DON,NHP,coo,iconf,-1);
	   }

	} else {
/* todo: donors_cooh */
	}

	if (issCOO(i,&io1,&io2)) {

	   AllInt(C,&lintp,io1,i,io2,0,3,H_ACC,COOmin,coo,iconf,-1);

	   ligtyp[lintp-1]->q0 = -0.5; 
	   ligtyp[lintp-1]->q1 =  0.0; 
	   ligtyp[lintp-1]->q2 = -0.5; 

	   AllInt(C,&lintp,io2,i,io1,0,3,H_ACC,COOmin,coo,iconf,-1);
	} else if (isCO(i,&io1)) {
	   AllInt(C,&lintp,io1,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	} else if (isCOmin(i,&io1)) {
	   AllInt(C,&lintp,io1,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	}
	if (isSO(i,&io1,&io2)) {
	   if (io1 != -1) AllInt(C,&lintp,io1,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	   if (io2 != -1) AllInt(C,&lintp,io2,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	}
	if (isNO2(i,&io1,&io2)) {
	   AllInt(C,&lintp,io1,i,io2,0,3,H_ACC,COOmin,coo,iconf,-1);
	   AllInt(C,&lintp,io2,i,io1,0,3,H_ACC,COOmin,coo,iconf,-1);

	} else if (isNO(i,&io1)) {
	   AllInt(C,&lintp,io1,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	}
	if (isPO(i,&io1,&io2,&io3)) {
	   if (io1 != -1) AllInt(C,&lintp,io1,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	   if (io2 != -1) AllInt(C,&lintp,io2,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	   if (io3 != -1) AllInt(C,&lintp,io3,i,0,0,2,H_ACC,CO,coo,iconf,-1);
	}
	if (isC3OH(i,&io1,&io2)) {
	   AllInt(C,&lintp,i,io1,io2,0,3,H_ACC,OSP3,coo,iconf,i);
	}
	if (isC2OH(i,&io1,&io2)) {
	   AllInt(C,&lintp,i,io1,io2,0,3,H_ACC,OSP2,coo,iconf,i);
	}
	if (isCOC(i,&io1,&io2)) {
	   AllInt(C,&lintp,i,io1,io2,0,3,H_ACC,COC,coo,iconf,-1);
	}
	if (isRF(i,&io1)) {
	   if (C->ianz[i] == 9) {
		AllInt(C,&lintp,i,io1,0,0,2,CH3,SPH1,coo,iconf,-1);
	   } else {
		AllInt(C,&lintp,i,io1,0,0,2,H_ACC,CO,coo,iconf,-1);
	   }
	}
	if (!isAZIDE(i)) {
	   if (isNaryl(i,&io1,&io2)) {
		AllInt(C,&lintp,i,io1,io2,0,3,H_ACC,NARYL,coo,iconf,-1);
	   }
	}
	if (isAMID(i,&io1,&io2)) {
	   AllInt(C,&lintp,i,io2,io1,0,3,H_ACC,AMID1,coo,iconf,-1);
	   AllInt(C,&lintp,i,io2,io1,0,3,H_ACC,AMID2,coo,iconf,-1);
	}
	if (isNamino(i,&io1,&io2,&io3)) {
	   AllInt(C,&lintp,i,io1,io2,io3,4,H_ACC,NAMINO,coo,iconf,-1);
	}
	if (isNT(i,&io1)) AllInt(C,&lintp,i,io1,0,0,2,H_ACC,CO,coo,iconf,-1);

	n = isCH3R(i);
	if (n == 1) {
	   AllInt(C,&lintp,i,0,0,0,1,CH3,SPH1,coo,iconf,-1);
	   indxm = lintp;
	   AllInt(C,&lintp,i,0,0,0,1,PHE_CH3,CH3_PHE,coo,iconf,-1);
	   ligtyp[indxm]->area.radius = 4.0;
	} else if (n == 2) {
	   AllInt(C,&lintp,i,0,0,0,1,CH2,SPH1,coo,iconf,-1);
	} else if (n == 3) {
	   AllInt(C,&lintp,i,0,0,0,1,CH,SPH1,coo,iconf,-1);
	}
	n = isCarR(i);
	if (n == 1 || n == 2) {
	   AllInt(C,&lintp,i,0,0,0,1,ARO,SPH1,coo,iconf,-1);
	}
	if (isS3(i)) AllInt(C,&lintp,i,0,0,0,1,SULFUR,SPH2,coo,iconf,-1);
	if (isSNH(i,&io1,&io2)) {
	   AllInt(C,&lintp,i,io1,io2,0,3,H_ACC,COC,coo,iconf,-1);
	}
   } // for (i=0; i < ndocka; i++) {

   if (isetconf) lintconf = lintp;
}

#define CONFWIN 2.0
static float ConfWin = CONFWIN;

void SortConf()
{
      int nt,i;
      float Emin;


      nt = -1;
 
      for (i=0; i < ntrif; i++) {
	if (TriFin[i] != NULL) {
	   if (TriFin[i]->eint > CONFWIN) {
	         if (TriFin[i]->coo != NULL) safefree((void **)&TriFin[i]->coo);
	         safefree((void **)&TriFin[i]);
		 TriFin[i] = NULL;
	   }
	}
      }

      for (i=ntrif; i > 0; i--) {
	if (TriFin[i] == NULL) {
	   nt = i;
	} else {
	   if (nt != -1) break;
	}
      }

      ntrif = nt;

      Compress_Tri_L();

if (debugdck) {
      fprintf(stderr,"After sort conformations:\n\n");
      for (i=0; i < ntrif; i++) {
	   if (TriFin[i] != NULL) {
		fprintf(stderr,"i %d eint %.3f\n",i,TriFin[i]->eint);
	   }
      }

      Write_Results("confchk.mol2",TriFin,ntrif,xyzp,1,0);
}

}

double CalcORI(int p1, int p2)
{
  double tt,r;
  int l;

  r = 0.0;

  for (l=0; l < 3; l++) {
      tt = ligtyp[p1]->ORI[l] - ligtyp[p2]->ORI[l];
      r = r + tt*tt;
  }

  return(r);
}

void FindSameTriS(int ind)
{
   int i,lig[3],act,CARR[MXCONFARR];
   double d12,d13,d23;
   double D12,D13,D23;

   for (i=0; i < 3; i++) {
      lig[i] = TriS[ind].lig[i];
   }

   d12 = CalcORI(lig[0],lig[1]);
   d13 = CalcORI(lig[0],lig[2]);
   d23 = CalcORI(lig[1],lig[2]);

   TriS[ind].nconf = 1;
   CARR[0] = TriS[ind].conf;

   for (i=0; i < ntriS; i++) {
	if (TriS[i].active && i != ind) {
	 if (!struct_cmp(&ligtyp[lig[0]]->area,
		&ligtyp[TriS[i].lig[0]]->area)) {
	  if (!struct_cmp(&ligtyp[lig[1]]->area,
		&ligtyp[TriS[i].lig[1]]->area)) {
	   if (!struct_cmp(&ligtyp[lig[2]]->area,
		&ligtyp[TriS[i].lig[2]]->area)) {

		D12 = CalcORI(TriS[i].lig[0],TriS[i].lig[1]);
		D13 = CalcORI(TriS[i].lig[0],TriS[i].lig[2]);
		D23 = CalcORI(TriS[i].lig[1],TriS[i].lig[2]);

	        if (ABS(D12-d12) < 0.3 && ABS(D13-d13) < 0.3 && 
			ABS(D23-d23) < 0.3 ) {
		   CARR[TriS[ind].nconf] = TriS[i].conf;
		   TriS[ind].nconf++;
		   TriS[i].active = 0;
		}
	   }
	  }
	 }
	}
   }

   TriS[ind].ConfArr = (int *) malloc(TriS[ind].nconf*sizeof(int));
   for (i=0; i < TriS[ind].nconf; i++) {
	TriS[ind].ConfArr[i] = CARR[i];
   }
}

int Find_Lig_Conf2(int n)
{
     int i,j,k;
     int Conformer,lig0,lig1,lig2;

     lig0 = TriS[n].lig[0];
     lig1 = TriS[n].lig[1];
     lig2 = TriS[n].lig[2];

     for (i=0; i < ligtyp[lig0]->nconf; i++) {
	if (ligtyp[lig0]->ConfArr != NULL) {
	   Conformer = ligtyp[lig0]->ConfArr[i];

           for (k=0; k < ligtyp[lig1]->nconf; k++) {
	      if (ligtyp[lig1]->ConfArr != NULL) {
	        if (Conformer == ligtyp[lig1]->ConfArr[k]) {

		   for (j=0; j < ligtyp[lig2]->nconf; j++) {
			if (ligtyp[lig2]->ConfArr != NULL) {
			   if (Conformer == 
				ligtyp[lig2]->ConfArr[j]) return(1);
			}
		   }

		}
	      }
	   }

	}
     }
     return(0);
}

int Find_Lig_Conf(int k,int itri)
{
     int i,iset1,iset2;

     iset1 = 0;

if (TriArr[itri] != NULL) {

     for (i=0; i < ligtyp[TriArr[itri]->lig[1]]->nconf; i++) {
	if (ligtyp[TriArr[itri]->lig[1]]->ConfArr != NULL) {
	   if (k == ligtyp[TriArr[itri]->lig[1]]->ConfArr[i]) {
		iset1 = 1;
	   }
	} else {
	   if (k == 0) {
		iset1 = 1;
	   }
	}
     }

     iset2 = 0;

     for (i=0; i < ligtyp[TriArr[itri]->lig[2]]->nconf; i++) {
	if (ligtyp[TriArr[itri]->lig[2]]->ConfArr != NULL) {
	   if (k == ligtyp[TriArr[itri]->lig[2]]->ConfArr[i]) {
		iset2 = 1;
	   }
	} else {
	   if (k == 0) {
		iset2 = 1;
	   }
	}
     }
}

     if (iset1 && iset2) return(1);
     return(0);
}

void TrimTriS(int np,int *ADPAIR1,int *ADPAIR2,int *PAIRT)
{
   int i,j,n,act,ntriso,iact;

   for (i=0; i < ntriS; i++) {
	for (j=0; j < np; j++) {
	   iact = 0;
	   if (ADPAIR1[j] == TriS[i].frags[0] && 
	       ADPAIR2[j] == TriS[i].frags[1]) iact++;	
	   if (ADPAIR1[j] == TriS[i].frags[1] && 
	       ADPAIR2[j] == TriS[i].frags[0]) iact++;	

	   if (ADPAIR1[j] == TriS[i].frags[0] && 
	       ADPAIR2[j] == TriS[i].frags[2]) iact++;	
	   if (ADPAIR1[j] == TriS[i].frags[2] && 
	       ADPAIR2[j] == TriS[i].frags[0]) iact++;	

	   if (ADPAIR1[j] == TriS[i].frags[1] && 
	       ADPAIR2[j] == TriS[i].frags[2]) iact++;	
	   if (ADPAIR1[j] == TriS[i].frags[2] && 
	       ADPAIR2[j] == TriS[i].frags[1]) iact++;	

   	   if (!iact) TriS[i].active = 0;

	}
   }

   for (i=0; i < ntriS; i++) {
	act = TriS[i].active;
	if (act) FindSameTriS(i);
   }

   
   n = 0;
   for (i=0; i < ntriS; i++) {
	if (TriS[i].active) {
	   TriS[n] = TriS[i];
	   n++;
	}
   }
   ntriS = n;
}

void FindProtBaseFrag()
{
    int i,j,nentries,fnd,imin,iminv,iminv2,ntrisc;
    LIGSTRU *lig_list;
    float e12av, emin, eminv,eminv2;

    if (ntris < 1) return;
    CalcETris(1);

    qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);

    lig_list = (LIGSTRU *) malloc(sizeof(LIGSTRU)*ntris);

    for (i=0; i < 3; i++) {
      if (TriArr[i] != NULL) {
	lig_list[0].prot[0] = TriArr[i]->prot[0];
	lig_list[0].prot[1] = TriArr[i]->prot[1];
	lig_list[0].prot[2] = TriArr[i]->prot[2];
	lig_list[0].esum  = TriArr[i]->eint;
	lig_list[0].emin  = TriArr[i]->eint;
	lig_list[0].nentries = 1;
	break;
      }
    }

    nentries = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   fnd = 0;
	   for (j=0; j < nentries; j++) {
		if (TriArr[i]->prot[0] == lig_list[j].prot[0] && 
		    TriArr[i]->prot[1] == lig_list[j].prot[1] &&
		    TriArr[i]->prot[2] == lig_list[j].prot[2]) {
			fnd = 1;
			lig_list[j].esum = lig_list[j].esum + TriArr[i]->eint;
			if (TriArr[i]->eint < lig_list[j].emin) 
				lig_list[j].emin = TriArr[i]->eint;
			lig_list[j].nentries++;
	   	}
	   }
	   if (fnd == 0) {
		lig_list[nentries].prot[0] = TriArr[i]->prot[0];
		lig_list[nentries].prot[1] = TriArr[i]->prot[1];
		lig_list[nentries].prot[2] = TriArr[i]->prot[2];
		lig_list[nentries].esum  = TriArr[i]->eint;
		lig_list[nentries].emin  = TriArr[i]->eint;
		lig_list[nentries].nentries = 1;
		nentries++;
	   }
	}
    }

    emin = BIGD;

    if (debugdck) {
	fprintf(stderr,"FindProtBaseFrag Base Fragment:\n\n");
	fprintf(stderr,"lig %d %d %d\n",
		lig_list[0].prot[0],lig_list[0].prot[1],lig_list[0].prot[2]);
	fprintf(stderr,"lig %d %d %d\n",
		lig_list[1].prot[0],lig_list[1].prot[1],lig_list[1].prot[2]);
	fprintf(stderr,"lig %d %d %d\n",
		lig_list[2].prot[0],lig_list[2].prot[1],lig_list[2].prot[2]);
    }

    ntrisc = 0;

    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {
	fnd = 0;
	if (TriArr[i]->prot[0] == lig_list[0].prot[0] && 
	       TriArr[i]->prot[1] == lig_list[0].prot[1] &&
	       TriArr[i]->prot[2] == lig_list[0].prot[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (TriArr[i]->prot[0] == lig_list[1].prot[0] && 
	       TriArr[i]->prot[1] == lig_list[1].prot[1] &&
	       TriArr[i]->prot[2] == lig_list[1].prot[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (TriArr[i]->prot[0] == lig_list[2].prot[0] && 
	       TriArr[i]->prot[1] == lig_list[2].prot[1] &&
	       TriArr[i]->prot[2] == lig_list[2].prot[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (!fnd) {
	    TriCooSafeFree(i);
	    TriSafeFreeTxt(i,"FindProtBaseFrag",
			"Reason: does NOT satisfy base fragment ligand combo");
	}
      }
    }

    Compress_Tri_L();

    if (debugdck) Write_Results("chk_prot.mol2",TriArr,ntris,&DCKxyz,0,0);
}

int Calc_Tri_Energies(int *iclos,
		float *q,float *vdwr,float *vdwe,
		float *ql,float *vdwrl,float *vdwel)
{
   int k,imin;
   float Einter,emin;

   emin = BIGD;
   imin = -1;

   for (k=0; k < ntris; k++) {

    if (TriArr[k] != NULL) {
      if (TriArr[k]->coo != NULL) {

	FillClos(iclos,k); 

	Einter = CalcInter(TriArr[k]->coo,xyzp->coo,iclos,
		q,vdwr,vdwe,ql,vdwrl,vdwel);

	TriArr[k]->eint = Einter;

	if (Einter < emin) {
	   emin = Einter;
	   imin = k;
	}
     }
    }
   }

   if (imin != -1) {
      fprintf(stderr,"Calc_Tri_Energies: Base Fragment: lig %d %d\n",
	TriArr[imin]->lig[0],TriArr[imin]->lig[1]);
   }

   return(imin);
}

int Tri_Energies()
{
   int k,l,imin,*iclos;
   float *q,*vdwr,*vdwe,*F;
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return(-1);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   if (ntris > 0) {
	   vdwscal = VDWSCAL;
   }

   imin = Calc_Tri_Energies(iclos,q,vdwr,vdwe,ql,vdwrl,vdwel);

   vdwscal = 1.0;

   safefree((void **)&q);
   safefree((void **)&vdwr);
   safefree((void **)&vdwe);
   safefree((void **)&F);

   return(imin);
}

void FindBaseFrag2()
{
    int i,j,nentries,fnd,imin,iminv,iminv2,ntrisc,imintri,icnt;
    LIGSTRU *lig_list;
    float e12av, emin, eminv, eminv2;

// assumes TriArr[]->eint already been calculated

    lig_list = (LIGSTRU *) malloc(sizeof(LIGSTRU)*ntris);

    icnt = 0;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   lig_list[icnt].lig[0] = TriArr[i]->lig[0];
	   lig_list[icnt].lig[1] = TriArr[i]->lig[1];
	   lig_list[icnt].lig[2] = TriArr[i]->lig[2];
	   lig_list[icnt].emin = TriArr[i]->eint;
	   icnt++;
	}
    }


    nentries = 5;
    if (icnt < nentries) nentries = icnt;

    emin   = BIGD;
    eminv  = BIGD;
    imin   = -1;
    iminv  = -1;

    for (i=0; i < icnt; i++) {
	if (lig_list[i].emin < eminv) {
	   eminv = lig_list[i].emin;
	   iminv = i;
 	}
    }


    if (1) {
	if (iminv != -1)
	   fprintf(stderr,"Base Fragment: iminv lig %d %d %d\n",lig_list[iminv].lig[0],lig_list[iminv].lig[1],lig_list[iminv].lig[2]);

    }

    ntrisc = 0;

    for (i=0; i < ntris; i++) {
	fnd = 0;
	for (j=0; j < icnt; j++) {
	   if (TriArr[i]->lig[0] == lig_list[j].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[j].lig[1]) {
		ntrisc++; fnd = 1;
	   }
	}
	if (!fnd) {
		TriCooSafeFree(i);
	   	TriSafeFreeTxt(i,"FindBaseFrag2",
			"Reason: does NOT satisfy base fragment ligand combo");
	}
    }

    Compress_Tri_L();

    for (i=0; i < ntris; i++) {
	   if (TriArr[i]->lig[0] == lig_list[iminv].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[iminv].lig[1]) {
		ntrisc++;
	   } else {
	    TriCooSafeFree(i);
	    TriSafeFreeTxt(i,"FindBaseFrag2 b",
			"Reason: does NOT satisfy base fragment ligand combo");
	   }
    }

    Compress_Tri_L();

    if (debugdck) Write_Results("chk_base2.mol2",TriArr,ntris,&DCKxyz,0,0);
}

void CalcETris(int opt)
{
   int i,j,k,l,n,it,*iclos;
   float *F,E,a,b,c,vl;
   float *q,*vdwr,*vdwe,dir[3],tdir[3];
   float ql[MXLIGA],vdwrl[MXLIGA],vdwel[MXLIGA];
   int frg[MXLIGA];
   float *wxyz,cen[3];

// calculate interaction energy between base fragment ligand (opt==0)
// and closest protein residues stored in iclos
// opt == 0, no van der Waals scaling. We need this to discern
// the best ligand triangle
// opt == 1, WITH van der waals scaling to get reasonable interaction energies
// This function is also used to get the top maxsol scoring ligand poses.
// For that we need the whole of the ligand turned on by setting frg[] = 1

   if (!AllArr(&q,&vdwr,&vdwe,&iclos,&F)) return;

   allFConf(&wxyz,ndocka);

   AssChg(q);
   AssVDW(vdwr,vdwe);
   AssVDWL(vdwrl,vdwel,ql);

   if (ntris > 0) {
	if (opt) {
	   vdwscal = VDWSCAL;
	   for (i=0; i < ndocka; i++)  {
		frg[i] = 1;
	   }
	} else {
	   for (i=0; i < ndocka; i++) {
	   }
	}
   } else {
	return;
   }

   for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {

	    if (TriArr[i]->coo == NULL) continue;

	    if (opt) {
	        FillClos(iclos,i);
		PickFull(frg,ndocka);
	    } else {
	        FillOpt(iclos,i);
		PickFrag(frg,i,ndocka);
	    }

	    for (k=0; k < ndocka; k++) {
		for (j=0; j < 3; j++) {
	   	   wxyz[3*k+j] = (float) TriArr[i]->coo[3*k+j];
		}
	    }

	    if (!FASTSLOW) {
	   	CalcFE(wxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	    } else {
	   	CalcFE(wxyz,xyzp->coo,iclos,q,vdwr,vdwe,
		ql,vdwrl,vdwel,F,&E,dir,frg);
	    }

	    TriArr[i]->eint = E;

	}
   }

   eint_calculated = 1;
   vdwscal = 1.0;

}

int Calc_RMSD()
{
   int i,j,k,irmsd;
   float rtmp,rmsd,rmsdm;

   rmsdm = BIGD;
   irmsd = -1;

   for (i=0; i<ntris; i++) { 
      rmsd = 0.0;
      for (k=0; k<ndocka; k++) { 
	for (j=0; j<3; j++) { 
	      rtmp = (CHKxyz.coo[k*3+j] - TriArr[i]->coo[k*3+j]);
	      rmsd = rmsd + rtmp*rtmp;
	}
      }
      rmsd = sqrt(rmsd/((float) ndocka));
      if (rmsd < rmsdm) {
	irmsd = i;
	rmsdm = rmsd;
      }
   }

   if (debugdck) fprintf(stderr,"mconformers pose with min. rmsd: %d conf# %d\n"
			,irmsd,TriArr[irmsd]->conf);

   return(irmsd);
}

int CHK_RMSD(TRISTRU *Tri, int cc)
{
   int i,j,k,irmsd;
   float rtmp,rmsd,rmsdm;

   rmsdm = BIGD;
   irmsd = -1;

   for (i=0; i<ntris; i++) { 
      rmsd = 0.0;
      for (k=0; k<ndocka; k++) { 
		for (j=0; j<3; j++) { 
	   	   rtmp = (Tri->coo[k*3+j] - TriArr[i]->coo[k*3+j]);
	   	   rmsd = rmsd + rtmp*rtmp;
		}
      }
      rmsd = sqrt(rmsd/((float) ndocka));

      if ((Tri->lig[0] == TriArr[i]->lig[0] &&
	   Tri->lig[1] == TriArr[i]->lig[1] &&
	   Tri->lig[2] == TriArr[i]->lig[2]) &&
      	  (Tri->prot[0] == TriArr[i]->prot[0] &&
	   Tri->prot[1] == TriArr[i]->prot[1] &&
	   Tri->prot[2] == TriArr[i]->prot[2]) 
	) {

           rmsd = 0.0;
	   for (k=0; k<ndocka; k++) { 
		for (j=0; j<3; j++) { 
	   	   rtmp = (Tri->coo[k*3+j] - TriArr[i]->coo[k*3+j]);
	   	   rmsd = rmsd + rtmp*rtmp;
		}
	   }

	   rmsd = sqrt(rmsd/((float) ndocka));

	   if (rmsd < rmsdm) {
		irmsd = i;
		rmsdm = rmsd;
	   }
      }
   }

   if (irmsd != -1) {
      Tri->conf = TriArr[irmsd]->conf;
   } else {
//      fprintf(stderr,"Tri->conf not set by CHK_RMSD: irsmd == -1\n");
   }

   if (debugdck && irmsd != -1) 
	fprintf(stderr,"min. RMSD %d nd stored pose with TriArr[%d] pose; conf# %d lig %d %d %d prot %d %d %d rmsd %.3f\n"
			,cc,irmsd,TriArr[irmsd]->conf,TriArr[irmsd]->lig[0],TriArr[irmsd]->lig[1],TriArr[irmsd]->lig[2],TriArr[irmsd]->prot[0],TriArr[irmsd]->prot[1],TriArr[irmsd]->prot[2],rmsdm);

   return(irmsd);
}

void Find_CHK_Conf()
{
   int i,irmsd;

   for (i=0; i < nchk; i++) {
	irmsd = CHK_RMSD(TriCHK[i],i);
   }
}

void ReapCHK()
{
    int i,j,k,size,ICHK[MAXCHK];

    if (ntris == 1) {
	DOCHK = 1;
	size = MXLIGA;
	alldck(&CHKxyz,&size);
	for (i=0; i < ndocka; i++) {
	   for (j=0; j<3; j++) {
		CHKxyz.coo[i*3+j] = TriArr[0]->coo[i*3+j];
	   }
	}
	
    }

    if (ntris > 0) {

	nchk = 0;

	for (k=0; k < ntris; k++) {
	   if (TriArr[k] != NULL) {
	     if (TriArr[k]->eint < 15.0 && k < MAXCHK) {
		ICHK[nchk] = k;
		nchk++;
	     }
	   }
	}

	for (k=0; k < nchk; k++) {
	   if (TriArr[k] != NULL) {
	      TriCHK[k]->conf = TriArr[ICHK[k]]->conf;
	      if (TriArr[k]->coo != NULL) {
	      	for (i=0; i < ndocka; i++) {
		   for (j=0; j<3; j++) {
			TriCHK[k]->coo[i*3+j] = TriArr[ICHK[k]]->coo[i*3+j];
		   }
	      	}

	      	for (j=0; j<3; j++) {
		   TriCHK[k]->lig[j]  = TriArr[ICHK[k]]->lig[j];
		   TriCHK[k]->prot[j] = TriArr[ICHK[k]]->prot[j];
	      	}
	      }
	   }
	}

	DOCHK = 2;
    }
}

void FindBaseFrag23(int opt)
{
    int i,j,nentries,fnd,imin,iminv,iminv2,ntrisc,istart,size;
    LIGSTRU *lig_list;
    float e12av, emin, eminv, eminv2;

    if (!eint_calculated) CalcETris(opt);

//   Conformers_Energies(&DCKxyz);

    if (debugdck) fprintf(stderr,"FindBaseFrag23: ntris %d\n",ntris);

    if (ntris <= 0) return;

    istart = -1;
    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   istart = i;
	   break;
	}
    }

    if (istart == -1) return;

    lig_list = (LIGSTRU *) malloc(sizeof(LIGSTRU)*ntris);

    lig_list[0].lig[0] = TriArr[istart]->lig[0];
    lig_list[0].lig[1] = TriArr[istart]->lig[1];
    lig_list[0].lig[2] = TriArr[istart]->lig[2];
    lig_list[0].esum   = TriArr[istart]->eint;
    lig_list[0].emin   = TriArr[istart]->eint;
    lig_list[0].emin2  = TriArr[istart]->eint;
    lig_list[0].nentries = 1;

    nentries = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   fnd = 0;
	   for (j=0; j < nentries; j++) {
		if (TriArr[i]->lig[0] == lig_list[j].lig[0] && 
		    TriArr[i]->lig[1] == lig_list[j].lig[1]) {
			fnd = 1;
			lig_list[j].esum = lig_list[j].esum + TriArr[i]->eint;
			if (TriArr[i]->eint < lig_list[j].emin) 
				lig_list[j].emin = TriArr[i]->eint;
			if (TriArr[i]->eint < lig_list[j].emin2 && 
				!(TriArr[i]->eint < lig_list[j].emin) ) 
				lig_list[j].emin2 = TriArr[i]->eint;
			lig_list[j].nentries++;
	   	}
	   }
	   if (fnd == 0) {
		lig_list[nentries].lig[0] = TriArr[i]->lig[0];
		lig_list[nentries].lig[1] = TriArr[i]->lig[1];
		lig_list[nentries].lig[2] = TriArr[i]->lig[2];
		lig_list[nentries].esum = TriArr[i]->eint;
		lig_list[nentries].emin = TriArr[i]->eint;
		lig_list[nentries].nentries = 1;
		nentries++;
	   }
	}
    }

    emin = BIGD;
    eminv = BIGD;
    eminv2 = BIGD;
    imin = -1;
    iminv = -1;
    iminv2 = -1;

    for (i=0; i < nentries; i++) {

	e12av = lig_list[i].esum / (float) lig_list[i].nentries;
	if (e12av < emin) {
	   emin = e12av;
	   imin = i;
	}
	if (lig_list[i].emin < eminv) {
	   eminv = lig_list[i].emin;
	   iminv = i;
	}
	if (lig_list[i].emin2 < eminv2) {
	   eminv2 = lig_list[i].emin2;
	   iminv2 = i;
	}
    }


    if (debugdck) {
	if (imin != -1)
	   fprintf(stderr,"Base Fragment: imin lig %d %d %d imin %d\n",lig_list[imin].lig[0],lig_list[imin].lig[1],lig_list[imin].lig[2],imin);
	if (iminv != -1)
	   fprintf(stderr,"Base Fragment: iminv lig %d %d %d iminv %d\n",lig_list[iminv].lig[0],lig_list[iminv].lig[1],lig_list[iminv].lig[2],iminv);
    }

    if (imin == -1 && iminv2 == -1) return;

    ntrisc = 0;

    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {
	fnd = 0;
	if (imin != -1) {
	   if (TriArr[i]->lig[0] == lig_list[imin].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[imin].lig[1]) {
		ntrisc++;
		fnd = 1;
	   }
	}
	if (iminv != -1) {
	   if (TriArr[i]->lig[0] == lig_list[iminv].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[iminv].lig[1]) {
		ntrisc++;
		fnd = 1;
	   }
	}
	if (iminv2 != -1 && opt == 0) {
	   if (TriArr[i]->lig[0] == lig_list[iminv2].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[iminv2].lig[1]) {
		ntrisc++;
		fnd = 1;
	   }
	}
	if (!fnd) {
	    TriCooSafeFree(i);
	    TriSafeFreeTxt(i,"FindBaseFrag23",
			"Reason: does NOT satisfy base fragment ligand combo");
	}
      }
    }

    Compress_Tri_L();

    if (debugdck) Write_Results("chk_base23.mol2",TriArr,ntris,&DCKxyz,1,0);

    ReapCHK();

}

void FindBaseFrag3(int opt)
{
    int i,j,nentries,fnd,imin,iminv,iminv2,ntrisc,istart,size;
    LIGSTRU *lig_list;
    float e12av, emin, eminv, eminv2;

    if (!eint_calculated) CalcETris(opt);

    if (debugdck) fprintf(stderr,"FindBaseFrag3: ntris %d\n",ntris);

    if (ntris <= 0) return;

    qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   istart = i;
	   break;
	}
    }

    lig_list = (LIGSTRU *) malloc(sizeof(LIGSTRU)*ntris);

    lig_list[0].lig[0] = TriArr[istart]->lig[0];
    lig_list[0].lig[1] = TriArr[istart]->lig[1];
    lig_list[0].lig[2] = TriArr[istart]->lig[2];
    lig_list[0].esum   = TriArr[istart]->eint;
    lig_list[0].emin   = TriArr[istart]->eint;
    lig_list[0].emin2  = TriArr[istart]->eint;
    lig_list[0].nentries = 1;

    nentries = 1;

    for (i=0; i < ntris; i++) {
	if (TriArr[i] != NULL) {
	   fnd = 0;
	   for (j=0; j < nentries; j++) {
		if (TriArr[i]->lig[0] == lig_list[j].lig[0] && 
		    TriArr[i]->lig[1] == lig_list[j].lig[1] &&
		    TriArr[i]->lig[2] == lig_list[j].lig[2]) {
			fnd = 1;
			lig_list[j].esum = lig_list[j].esum + TriArr[i]->eint;
			if (TriArr[i]->eint < lig_list[j].emin) 
				lig_list[j].emin = TriArr[i]->eint;
			if (TriArr[i]->eint < lig_list[j].emin2 && 
				!(TriArr[i]->eint < lig_list[j].emin) ) 
				lig_list[j].emin2 = TriArr[i]->eint;
			lig_list[j].nentries++;
	   	}
	   }
	   if (fnd == 0) {
		lig_list[nentries].lig[0] = TriArr[i]->lig[0];
		lig_list[nentries].lig[1] = TriArr[i]->lig[1];
		lig_list[nentries].lig[2] = TriArr[i]->lig[2];
		lig_list[nentries].esum = TriArr[i]->eint;
		lig_list[nentries].emin = TriArr[i]->eint;
		lig_list[nentries].nentries = 1;
		nentries++;
	   }
	}
    }

    emin = BIGD;
    eminv = BIGD;
    eminv2 = BIGD;
    imin = -1;
    iminv = -1;
    iminv2 = -1;


    if (debugdck) {
	if (imin != -1)
	   fprintf(stderr,"Base Fragment: imin lig %d %d %d imin %d\n",lig_list[imin].lig[0],lig_list[imin].lig[1],lig_list[imin].lig[2],imin);
	if (iminv != -1)
	   fprintf(stderr,"Base Fragment: iminv lig %d %d %d iminv %d\n",lig_list[iminv].lig[0],lig_list[iminv].lig[1],lig_list[iminv].lig[2],iminv);
	if (iminv2 != -1)
	   fprintf(stderr,"Base Fragment: iminv2 lig %d %d %d iminv2 %d\n",lig_list[iminv2].lig[0],lig_list[iminv2].lig[1],lig_list[iminv2].lig[2],iminv2);
    }

    if (imin == -1 && iminv2 == -1) return;

    ntrisc = 0;

    for (i=0; i < ntris; i++) {
      if (TriArr[i] != NULL) {
	fnd = 0;
	if (TriArr[i]->lig[0] == lig_list[0].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[0].lig[1] &&
	       TriArr[i]->lig[2] == lig_list[0].lig[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (TriArr[i]->lig[0] == lig_list[1].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[1].lig[1] &&
	       TriArr[i]->lig[2] == lig_list[1].lig[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (TriArr[i]->lig[0] == lig_list[2].lig[0] && 
	       TriArr[i]->lig[1] == lig_list[2].lig[1] &&
	       TriArr[i]->lig[2] == lig_list[2].lig[2]) {
		ntrisc++;
		fnd = 1;
	}
	if (!fnd) {
	    TriCooSafeFree(i);
	    TriSafeFreeTxt(i,"FindBaseFrag3",
			"Reason: does NOT satisfy base fragment ligand combo");
	}
      }
    }

    Compress_Tri_L();

    if (debugdck) Write_Results("chk_base3.mol2",TriArr,ntris,&DCKxyz,1,0);

    ReapCHK();
/*
    if (ntris == 1) {
	DOCHK = 1;
	size = MXLIGA;
	alldck(&CHKxyz,&size);
	for (i=0; i < ndocka; i++) {
	   for (j=0; j<3; j++) {
		CHKxyz.coo[i*3+j] = TriArr[0]->coo[i*3+j];
	   }
	}
	
    }
*/
}

void eint_shrink(cut)
int cut;
{	
	int n,i;

	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);

	n = MINI(ntris,cut);

	for (i = 0; i < ntris; i++) {
	   if (i >= n) {
		if (TriArr[i] != NULL) {
	 	   TriCooSafeFree(i);
	    	   TriSafeFreeTxt(i,"qsort eint`",
			"Reason: itri > 18");
		}
	   }
	}

	ntris = n;
}

void Get_HAS_SPEC(int imode)
{
   int i,j,k,i1;
   int ninp[4],Ifrag;
   int *inpp[4],irng,irs,iatomsd,mxnatd;
   int nacc,ndon,nphec,npher,naro;
   int *iacc, *idon, *iphec, *ipher, *iaro;
   int iring[6],oring[6],ngrp,ligselp;
   COOSTRU *pp;

   HAS_SPEC = 0;

   ligselp = LigSel - 1;

   if (pdbcode != NULL) {

      if ((strcasecmp(pdbcode,"7ndo") == 0 || strcasecmp(pdbcode,"1err") == 0
	  || strcasecmp(pdbcode,"2qxs") == 0)
	&& strcmp(hetptr.HetAtm[ligselp],"RAL") == 0) {
	HAS_SPEC = 1;
      }

      if (strcasecmp(pdbcode,"3erd") == 0
       && strcmp(hetptr.HetAtm[ligselp],"DES") == 0) {
	HAS_SPEC = 1;
      }

      if (strcasecmp(pdbcode,"1a52") == 0
       && strcmp(hetptr.HetAtm[ligselp],"EST") == 0) {
	HAS_SPEC = 1;
      }

      if (strcasecmp(pdbcode,"3k3e") == 0
       && strcmp(hetptr.HetAtm[ligselp],"PDB") == 0) {
	HAS_SPEC = 0;
	EXTRA_IP = 1;
      }

      if (strcasecmp(pdbcode,"1a28") == 0
       && strcmp(hetptr.HetAtm[ligselp],"STR") == 0) {
	HAS_SPEC = 1;
      }

      if (strcasecmp(pdbcode,"1x7e") == 0
       && strcmp(hetptr.HetAtm[ligselp],"244") == 0) {
	HAS_SPEC = 1;
      }

      if (strcasecmp(pdbcode,"4dfr") == 0
       && strcmp(hetptr.HetAtm[ligselp],"mtx") == 0) {
	HAS_SPEC = 0;
	EXTRA_IP = 1;
      }

      if (strcasecmp(pdbcode,"5ccr") == 0
       && strcmp(hetptr.HetAtm[ligselp],"4zt") == 0) {
	HAS_SPEC = 0;
	EXTRA_IP = 1;
      }

      if (strcasecmp(pdbcode,"4isi") == 0
       && strcasecmp(hetptr.HetAtm[ligselp],"1gg") == 0) {
	HAS_SPEC = 0;
	EXTRA_IP = 1;
      }
   }

}

void intcor_(intc,rout,isel,inum)
int *intc;
int *rout;
int *isel;
int *inum;
{

	intcod_(intc,rout,isel,inum,xyzp->coo);

}

static char *tab10 = "table10";
static char *tab15 = "table15";

void ProcLig(imode)
int imode;
{
   int i,i1,in,j,k,kn,l,m,indx,nring,iret,aro,c2ar,n2ar,n2art,n2d,iattmp,ipdbtmp;
   int jm1,jp1,io1,io2,io3,ierr,n,ninp[4],itel,maxsol,ic,pl,Ifrag,NoFrag;
   int *inpp[4],Score_Org_Ligand,indxm,irng,irs,iflg,iatomsd,mxnatd;
   int nacc,ndon,nphec,npher,naro,IMULTCONF;
   int ncacc,ncdon,ncphec,ncpher,ncaro;
   int ii,SET_ACTIVEG;
   int *iacc, *idon, *iphec, *ipher, *iaro;
   int *ADPAIR1, *ADPAIR2, *PAIRT;
   int iring[6],oring[6],iele[4],ngrp,npair,npair_nolink,ligselp;
   int *ianztmp,nt,tl0,tl1,tl2,l0,l1,l2,irmsd;
   int *ityptmp;
   time_t curtime;
   COOSTRU *pp;
   float fsmall,fbig,f;
   float flsmall,flbig,fl;
   double secnds;
   int secs;

   if (imode) Get_HAS_SPEC(imode);

   VDWSCAL = 0.1;
   SET_ACTIVEG = 0;

   ligselp = LigSel - 1;

   if (pdbcode != NULL) {
      if ((strcmp(pdbcode,"3k3e") == 0 && 
	strcmp(hetptr.HetAtm[ligselp],"PDB") == 0)) {
	FASTSLOW = 0;
      }

      if (FASTSLOW && !(strcmp(pdbcode,"7ndo") == 0 && 
	strcmp(hetptr.HetAtm[ligselp],"RAL") == 0)
                && !(strcmp(pdbcode,"4dfr") == 0 && 
	strcmp(hetptr.HetAtm[ligselp],"MTX") == 0)
                && !(strcmp(pdbcode,"5ccr") == 0 && 
	strcmp(hetptr.HetAtm[ligselp],"4ZT") == 0)
                && !(strcmp(pdbcode,"4isi") == 0 && 
	strcmp(hetptr.HetAtm[ligselp],"1GG") == 0)) {
	OPTCUT = 600;
      } else {

// 7ndo,4dfr,5ccr,4isi always have OPTCUT 3500

	OPTCUT = 3500;
      }
   } else {
	OPTCUT = 3500;
   }

   VDWSCAL = 0.1;
   IMULTCONF = 0;
   DCKLIGPROC = 1;
   Ifrag = -1;
   indx = 0;
   NoFrag = 0;
   MapConformers = 1;
   e12_calculated = 0;
   eint_calculated = 0;

   pp = xyzp;

   if (imode == 1) {
      iatomsd = *(xyzp->iatoms);
      mxnatd  = *(xyzp->mxnat);
      xyzp = &DCKxyz;
      setiat(ndocka);
   } else {
      ndocka = *xyzp->iatoms;
   }

   for (i=0; i < ndocka; i++) {
	xyzp->lring[i] = 0;
	xyzp->lwrit[i] = 0;
	xyzp->iaton[i] = 2;
   }

   for (i=0; i < ndocka; i++) {

	i1 = i + 1;
	
	xyzp->iaton[i] = 2;
	ispnd_(&irs,&i1,&irng,&ONE,&ZERO,
	   xyzp->qat,xyzp->ianz,xyzp->iaton,xyzp->iconn,xyzp->lwrit,xyzp->lring);
	singleb.irsd[i] = IHBT[irs-1];

   }

   singleb.N = 0;

   lintp = 0;

   AssLig(xyzp,xyzp->coo,-1);
   ExtraFrag(xyzp);

   Fragmentise(xyzp);

   for (j=0; j < lintp; j++) FrgInt(j);

   if (imode == 1) {
      xyzp = pp;
      setiat(iatomsd);
      *(xyzp->mxnat)  = mxnatd;
   }

   iacc = (int *) malloc(sizeof(int)*lintp);
   idon = (int *) malloc(sizeof(int)*lintp);
   iphec = (int *) malloc(sizeof(int)*lintp);
   ipher = (int *) malloc(sizeof(int)*lintp);
   iaro = (int *) malloc(sizeof(int)*lintp);

   prtypes(ligtyp,lintp,iacc,&nacc,idon,&ndon,iphec,&nphec,ipher,&npher,iaro,&naro);

   if (imode == 0) {
      ndocka = *xyzp->iatoms;
      Create_Conformers(0,xyzp);
      Sanitise_Conformers();
      if (ntrif == -1) CopyLig(xyzp);
if (debugdck) Write_Results("conformers.mol2",TriFin,ntrif,xyzp,1,0);
      Loop_Opt_Dih(0,xyzp,1);
      return;
   }

   ninp[0] = nacc; ninp[1] = ndon; ninp[2] = nphec; ninp[3] = npher; 
   inpp[0] = iacc; inpp[1] = idon; inpp[2] = iphec; inpp[3] = ipher;

if (debugdck) fprintf(stderr,"ndon %d nphec %d npher %d nacc %d\n",ndon,nphec,npher,nacc);
   ntriS = 0;

   ngrp = 2;
 
   time(&begtime);

if (debugdck) {
time(&curtime);
fprintf(stderr,"Docking Begin Time: %s\n",ctime(&curtime));
}

   if (Monitor_AccDon(nacc,ndon,iacc,idon,&npair,&npair_nolink)) {
	ngrp = 3;
if (debugdck) fprintf(stderr,"After Monitor_AccDon: ngrp %d\n",ngrp);
   } else {
//	npher = 0;
//	ninp[3] = 0;
   }

if (debugdck) fprintf(stderr,"npair %d npairl %d\n",npair,npair_nolink);


   for (i=0; i < MAXTRI; i++) {
	TriArr[i] = NULL;
	TriArrCopy[i] = NULL;
   }

   ligselp = LigSel - 1;
   if (ligselp >= 0) {
	if (strcmp(hetptr.HetAtm[ligselp],"1GG") == 0) UseOld = 1;
	if (strcmp(pdbcode,"7ndo") == 0 
	   && strcmp(hetptr.HetAtm[ligselp],"RAL") == 0) {
	   if (DCKdev < 1.0) {
	      DCKdev = 1.0;
	      fprintf(stderr,"Increased DCKdev to %6.2f\n",DCKdev);
	   } else {
	      fprintf(stderr,"Increased DCKdev to %6.2f\n",DCKdev);
	   }
	}
   }

   if (npair_nolink == 0) {
	Ifrag = 0;
	MapConformers = 0;
   } else {

	fprintf(stderr,"Start Setup_Distance_Tables\n");
 
if (debugdck) {
  time(&curtime);
  fprintf(stderr,"Begin Setup_Distance_Tables Time: %s\n",ctime(&curtime));
}
	if (access(tab10,F_OK) == 0) {
	   RD_table(tab10);
	} else {
	   Setup_Distance_Tables();
	   Wrt_table(tab10);
	}

if (debugdck) {
  time(&curtime);
  fprintf(stderr,"End Setup_Distance_Tables Time: %s\n",ctime(&curtime));
}


	for (i=0; i < ngrp; i++) {
	   for (j=0; j < ngrp; j++) {
		for (k=0; k < ngrp; k++) {
		   Harvest_Triples(ninp[i],ninp[j],ninp[k],
			inpp[i],inpp[j],inpp[k]);
		}
	   }
	}

if (debugdck) fprintf(stderr,"Harvest_Triples: ntriS %d\n\n",ntriS);

	Tris_NoLink();
	if (npair && ntriS > 150) Sub_Selection_Tris();

time(&endtime);
secnds = difftime(endtime,begtime);
secs = (int) secnds;

	Gen_triples();

if (debugdck) {
	fprintf(stderr,"aft gen_triples:\n");
	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) PrtTrp(i);
	}
}

	if (UseOld) {
	   Ifrag = CalcSchIntOld(0);
	} else {
	   Ifrag = CalcSchInt(0);
	}

   }

   if (imode == 1) {
      iatomsd = *(xyzp->iatoms);
      mxnatd  = *(xyzp->mxnat);
      xyzp = &DCKxyz;
      setiat(ndocka);

      if (Ifrag == -1) Ifrag = 0;
      Create_Conformers(Ifrag,xyzp);
      Sanitise_Conformers();
      if (ntrif == -1) CopyLig(xyzp);

if (debugdck) Write_Results("conformers.mol2",TriFin,ntrif,xyzp,1,0);
      SortConf();

   }

   if (ntriS == 0 || npair_nolink == 0) {

	ReleaseLig();
	lintp = 0;
	IMULTCONF = 1;
	MapConformers = 0;
	safefree((void **) &iacc);
	safefree((void **) &idon);
	safefree((void **) &iphec);
	safefree((void **) &ipher);
	safefree((void **) &iaro);

// These two lines are here to test ONE conformer, that has smallest RMSD
// with the crystal conformer

	lintp = 0;
	for (i=0; i < ntrif; i++) {
	   if (TriFin[i] != NULL) {
	      AssLig(&DCKxyz,TriFin[i]->coo,i);
	   }
	}
	for (j=0; j < lintp; j++) FrgInt(j);

	Compress_Ligtyp_List();

	iacc = (int *) malloc(sizeof(int)*lintp);
	idon = (int *) malloc(sizeof(int)*lintp);
	iphec = (int *) malloc(sizeof(int)*lintp);
	ipher = (int *) malloc(sizeof(int)*lintp);
	iaro  = (int *) malloc(sizeof(int)*lintp);
	ADPAIR1  = (int *) malloc(sizeof(int)*lintp);
	ADPAIR2  = (int *) malloc(sizeof(int)*lintp);
	PAIRT    = (int *) malloc(sizeof(int)*lintp);

	for (j=0; j < lintp; j++) {
		ADPAIR1[j] = -1;
		ADPAIR2[j] = -1;
		PAIRT[j]   =  0;
	}

	prtypes(ligtyp,lintp,iacc,&nacc,idon,&ndon,iphec,&nphec,
		ipher,&npher,iaro,&naro);

// we need a routine that takes an array such as iacc and a conformer number
// and create a specific subselection array

	ninp[0] = nacc; ninp[1] = ndon; ninp[2] = nphec; ninp[3] = npher;
	inpp[0] = iacc; inpp[1] = idon; inpp[2] = iphec; inpp[3] = ipher;

	ntriS = 0;

// This call is put in here to increase DCKCOFF to 15.0 if no ACC/DON pair
// is found with DCKCOFF 10.0
// as a side effect it also sets npair and npair_nolink

	if (Monitor_AccDon_Conformers(nacc,ndon,iacc,idon,&npair,
		&npair_nolink,ADPAIR1,ADPAIR2,PAIRT)) {
	   ngrp = 3;
	   ngrp = 2;
if (debugdck) fprintf(stderr,"After Monitor_AccDon_Conformers: ngrp %d\n",ngrp);
	} else {
//	   npher = 0;
//	   ninp[3] = 0;
	}

	fprintf(stderr,"2nd: Start Setup_Distance_Tables\n");

	if (npair_nolink == 0) {

	   Harvest_Triples_NoFrag(ndon,nphec,naro,idon,iphec,iaro);
	   Harvest_Triples_NoFrag(ndon,npher,naro,idon,ipher,iaro);
	   Harvest_Triples_NoFrag(nacc,nphec,naro,iacc,iphec,iaro);
	   Harvest_Triples_NoFrag(nacc,npher,naro,iacc,ipher,iaro);

	} else {

	   FiltAD = 3;
	   Harvest_Triples_NoFrag(ndon,ndon,nphec,idon,idon,iphec);
	   Harvest_Triples_NoFrag(ndon,ndon,npher,idon,idon,ipher);

	   FiltAD = 1;
	   Harvest_Triples_NoFrag(ndon,nacc,nphec,idon,iacc,iphec);
	   Harvest_Triples_NoFrag(ndon,nacc,npher,idon,iacc,ipher);

	   FiltAD = 2;
	   Harvest_Triples_NoFrag(nacc,nacc,nphec,iacc,iacc,iphec);
	   Harvest_Triples_NoFrag(nacc,nacc,npher,iacc,iacc,ipher);

	   if (ntriS == 0) {
	      SET_ACTIVEG = 1;
	      Harvest_Triples_NoFrag(nacc,nacc,naro,iacc,iacc,iaro);
	   }

	   TrimTriS(npair_nolink,ADPAIR1,ADPAIR2,PAIRT);
	   Tris_NoLink();
	}

	if (SET_ACTIVEG) ACTIVE_GROUPS = 5;

	if (access(tab15,F_OK) == 0) {
	   RD_table(tab15);
	} else {
	   Setup_Distance_Tables();
	   Wrt_table(tab15);
	}
if (debugdck) fprintf(stderr,"Harvest_Triples_NoFrag: ntriS %d\n\n",ntriS);
	if ((strcmp(pdbcode,"3k3e") == 0)
	&& strcmp(hetptr.HetAtm[ligselp],"PDB") == 0) {
	   Gen_triples();
	} else {
	   Gen_triples_conf();
	}

if (debugdck) {
	fprintf(stderr,"aft 2nd gen_triples: ntris %d\n",ntris);
	for (i=0; i < ntris; i++) {
	   if (TriArr[i] != NULL) PrtTrp(i);
	}
//	if (strcmp(pdbcode,"3k3e") == 0) DelTriNOT(20,14,0,151,150,160,0);
//	for (i=0; i < ntris; i++) {
//	   if (TriArr[i] != NULL) PrtTrp(i);
//	}
}

	if (imode == 1) {
	   xyzp = pp;
	   setiat(iatomsd);
	   *(xyzp->mxnat)  = mxnatd;
	}

	if (ntris == -1) {
		fprintf(stderr,"No matches found ntris -1\n");
		return;
	}

	if (HAS_SPEC && npair_nolink) {
	   CalcSchInt_Spec(npair_nolink);
	} else {
	   CalcSchInt(0);
	}

	safefree((void **) &iacc);
	safefree((void **) &idon);
	safefree((void **) &iphec);
	safefree((void **) &ipher);
	safefree((void **) &iaro);
	safefree((void **) &ADPAIR1);
	safefree((void **) &ADPAIR2);
	safefree((void **) &PAIRT);

	if (ntris == -1) {
		fprintf(stderr,"No matches found ntris -1\n");
		return;
	}

   }

   if (imode == 1) {
      xyzp = pp;
      setiat(iatomsd);
      *(xyzp->mxnat)  = mxnatd;
   }


if (debugdck) fprintf(stderr,"bef CalcAllInt: ntris %d\n",ntris);

   if (HAS_SPEC == 1)  {
	FilterTris_Spec();
	FindBaseFrag23(0);
   }
 
   CalcAllInt(0,0);


if (debugdck) fprintf(stderr,"aft CalcAllInt: ntris %d\n",ntris);

if (debugdck) {
   Write_Results("befrem.mol2",TriArr,ntris,&DCKxyz,0,0);
}

   RemCC_All(0);

if (debugdck) {

   fprintf(stderr,"Bef aftrem.mol2 ntris %d\n",ntris);

   Write_Results("aftrem.mol2",TriArr,ntris,&DCKxyz,0,0);

   fprintf(stderr,"after RemCC_All:  ntris %d\n",ntris);
}

   Compress_Tri_L();

if (debugdck) fprintf(stderr,"Bef Linkage_List ntris %d\n",ntris);


// If we leave this in we dont get the any solutions with negative energy
// passing this point. So the good ones are taken out !!!!!
// Perhaps we should consider doing the linkage with e12 !!!

//   Commented out because this routine takes away the best hits
//   if (ntris > 30 && ntris < 1000) Linkage_List(CLUSRMS);

   Compress_Tri_L();

if (debugdck) fprintf(stderr,"after Compress_Tri_L:  ntris %d\n",ntris);

   if (!INVESTIGATE) Compress_Tri_List_e12();

if (debugdck) Write_Results("dockbef.mol2",TriArr,ntris,&DCKxyz,2,0);

   UniqList();

   if (HAS_SPEC) {
	int maxsol,n,i1,nh;

	if (PRECISE) {
	   maxsol = dcksol*2;
	} else {
	   maxsol = dcksol;
	}

	if (ntrif <= 8) {
	   if (ntris > 0) {
		Conformers_Energies(&DCKxyz);
		qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	   }
	} else {
	   if (eint_calculated) {
		qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	   } else {
	      if (ntris > 0) {
		qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpe12);
	      }
	   }
	}

	n = MINI(ntris,1100);

	for (i1 = 0; i1 < ntris; i1++) {
	    if (HAS_SPEC == 1) {
		if (i1 >= n) {
		   if (TriArr[i1] != NULL) {
	 		TriCooSafeFree(i1);
	    		TriSafeFreeTxt(i1,"qsort cmpe12",
			"Reason: itri > 200");
		   }
		}
	    }
	}

	if (HAS_SPEC == 1) ntris = n;

if (debugdck) {
	if (eint_calculated) {
		Write_Results("aftcmpe12.mol2",TriArr,ntris,&DCKxyz,1,0);
	} else {
		Write_Results("aftcmpe12.mol2",TriArr,ntris,&DCKxyz,2,0);
	}
}

   }

   if (HAS_SPEC == 1) {

	FindProtBaseFrag();

	if (MapConformers) Map_Conformers(1);

   } else {

	FindBaseFrag3(0);
   }

   if (MapConformers) {

	FindBaseFrag3(0);
	if (FASTSLOW) {
	   if (ntris > 10) eint_shrink(18);
	}
	OptTris();

	if (!HAS_SPEC) {
	    Map_Conformers(0);
	}

   }

if (debugdck) fprintf(stderr,"after #MapConformers %d ntris %d\n",MapConformers,ntris);

if (debugdck) {
   if (MapConformers) {
	Write_Results("mconformersa.mol2",TriArr,ntris,&DCKxyz,1,0);

	if (DOCHK == 1) irmsd = Calc_RMSD();
	if (DOCHK == 2) Find_CHK_Conf();

   	time(&endtime);
   	secnds = difftime(endtime,begtime);
   	secs = (int) secnds;

	fprintf(stderr,"end Map_Conformers: ntris %d took:\n\n",ntris);
	ConvertSectoDay(secs);
	fprintf(stderr,"\n\n");
   }
}

   if (MapConformers) {
	int maxsol,n,i,fnd;
	double dst,tt;

if (debugdck) {
   	time(&endtime);
   	secnds = difftime(endtime,begtime);
   	secs = (int) secnds;

	fprintf(stderr,"begin Map_Conformers2: ntris %d took:\n\n",ntris);
	ConvertSectoDay(secs);
	fprintf(stderr,"\n\n");
}

	if (DCKMETH == 0) {

	   for (i = 0; i < ntris; i++) {
		if (TriArr[i] != NULL) {
		   if (TriArr[i]->coo != NULL) {
			tt = 0.0;
			for (j = 0; j < 3; j++) {
			   dst = DCKCNT[j] - TriArr[i]->coo[LCNT*3+j];
			   dst = dst *dst;
			   tt = tt + dst;
		        }
		        TriArr[i]->dcnt = (float) tt;
		    }
		}
	   }

	   if (ntris > 0) {
	      qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpd);
	   }

	   n = ntris;
	   for (i = 0; i < ntris; i++) {
	     if (TriArr[i] != NULL) { 
		if (TriArr[i]->dcnt > 150.0) {
		   n = i; break;
	 	}
	     }
	   }

	   for (i = 0; i < ntris; i++) {
		if (i >= n) {
		   if (TriArr[i] != NULL) { 
			TriCooSafeFree(i);
			TriSafeFreeTxt(i,"cmpd qsort",
			"Reason: dcnt > 150.0 ");
		   }
		}
	   }

	   ntris = n;

	   ReapCHK();

if (debugdck) {
   	time(&endtime);
   	secnds = difftime(endtime,begtime);
   	secs = (int) secnds;

	   fprintf(stderr,"end Map_Conformers2: ntris %d took:\n\n",ntris);
	   ConvertSectoDay(secs);
	   fprintf(stderr,"\n\n");
	   Write_Results("mconformersb.mol2",TriArr,ntris,&DCKxyz,1,0);
}
	   Calc_Overlap2();

	   if (ntris > 0) {
	      qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	   }

	   if (FASTSLOW) {
	      if (ntris > 10) eint_shrink(5000);
	   }

	   vdwscal_memory = VDWSCAL;
	   vdwscal = VDWSCAL;
	   CalcETris(1);

	   if (FASTSLOW) {
	      if (ntris > 10) eint_shrink(600);
	   }

	   vdwscal_memory = VDWSCAL;
	   vdwscal_memory = 1.0;

	} else {

	   fnd = 0;
	   maxsol = dcksol*160;
	   n = MINI(ntris,maxsol);

	   CalcETris(1);

	   if (ntris > 0) {
		qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	   }

	   for (i = 0; i < ntris; i++) {
		if (i >= n) {
		   if (TriArr[i] != NULL) { 
			   TriCooSafeFree(i);
			   TriSafeFreeTxt(i,"CalcEtris qsort",
				"Reason: itri > n (dcksol*160)");
		   }
		}
	   }

	   ntris = n;
	   if (debugdck) Write_Results("mconformersb.mol2",TriArr,ntris,&DCKxyz,1,0);
	   Calc_Overlap();

	}

if (ntris > 0) {
      qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
}

	for (i = 0; i < ntris; i++) {
	   TransForm_Tri3to2(TriArr[i]);
	   TransForm_Tri3(TriArr[i]);
	}

	FilterTris();

   } else {
	if (ntris > 0) {
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
	}
   }

if (debugdck) {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"begin Loop_Opt_Dih: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}
   Loop_Opt_Dih(Ifrag,&DCKxyz,0);

if (debugdck) {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"end Loop_Opt_Dih: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
   fprintf(stderr,"bef dockdih write:\n");

   Write_Results("dockdih.mol2",TriArr,ntris,&DCKxyz,1,0);
}

// CalcAllInt calculates e12 = interaction energy between protein and
// ligand. perhaps at this point it should be calculating Etot:
// Etot: Etot = e12 + eint
// after this do an other sort this time on Etot

   CalcAllInt(debugdck,1);

   if (ntris > 0) {
	qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
   }

   Score_Org_Ligand = 0;
   if (Score_Org_Ligand) OrgLig();

   if (MapConformers) RemCC_All(1);

//   Commented out because this routine takes away the best hits
//   if (ntris > 30 && ntris < 1000) Linkage_List(CLUSRMS2);
   Compress_Tri_L();

if (debugdck) {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"begin Conformers_Energies: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}
   Conformers_Energies(&DCKxyz);

if (debugdck) {
   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"end Conformers_Energies: ntris %d took:\n\n",ntris);
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");
}
//   Commented out because this routine takes away the best hits
//   if (ntris > 30 && ntris < 1000) Linkage_List(CLUSRMS2);

   if (ntris > 0) {
	   Compress_Tri_L();
	   qsort((TRISTRU *) TriArr, ntris, sizeof(TRISTRU *), cmpeint);
   }

   if (strcmp(pdbcode,"4isi") == 0
	&& strcmp(hetptr.HetAtm[ligselp],"1GG") == 0) {

	j=3;
	for (i=0; i < ntris; i++) {
	   if (Match_tri(TriArr[i],62,64,63,68,76,67)) {
		TriArr[j] = TriArr[i];
		j++;
	   }
	}
	ntris = j;
   }

if (debugdck) fprintf(stderr,"ntris %d dckout %s\n",ntris,dckout);

   Write_Results(dckout,TriArr,ntris,&DCKxyz,1,1);

   time(&endtime);
   secnds = difftime(endtime,begtime);
   secs = (int) secnds;

   fprintf(stderr,"Docking took:\n\n");
   ConvertSectoDay(secs);
   fprintf(stderr,"\n\n");

   if (chmod("./log",0777)) if (debugdck) fprintf(stderr,"End of docking\n");

}

int nline(char *str)
{
   int i,i1,i2,n;

   if (COO[istruct]->memfil.str != NULL) {

	i1 = COO[istruct]->memfil.line_index[COO[istruct]->memfil.currl];
	COO[istruct]->memfil.currl++;

	if (COO[istruct]->memfil.currl < COO[istruct]->memfil.nlines) {
	   i2 = COO[istruct]->memfil.line_index[COO[istruct]->memfil.currl];
	   n = i2 - i1 - 1;
	} else {
	   if (COO[istruct]->memfil.currl == COO[istruct]->memfil.nlines) {
		n = COO[istruct]->memfil.size - i1 - 1;
	   } else {
	   }
	}

	if (n > MXSTRFOR) n = MXSTRFOR;
	if (n < 0) n = 0;

	strncpy(str,&COO[istruct]->memfil.str[i1],(size_t) n);
	str[n] = '\n';
	for (i=n; i<137; i++) str[i] = ' ';
   }
}

int GetLineIndx(int idel,FILEOP *fileop)
{
   int i,ipos;

   ipos = fileop->fpos[idel];

   for (i=0; i < fileop->nlines; i++) {
	if (fileop->line_index[i] == ipos) return(i);
   }

   return(-1);
}

static char molstruc[MAXPATHLEN] = "dock.xyz";
static float mol_q[MXLIGA],mol_vdwr[MXLIGA],mol_vdwe[MXLIGA];

int GetLig()
{
	int i,j,k,i1,it,idum,igttnk,idebug,iffset,ipdbon,iheat,irng,irs,n;
	int iatomsd,mxnatd,size,fftmp,lmin;
	double rdum,heat,tt,dd,dmin;
	FILEOP tmpfil;
	FILEOP nfil = {NULL, NULL, 0, 0, 0, 0};
	char *ss;
	double *ppcoo;
	int *ppanz,*ppatclr;
	COOSTRU *pp;

	size = MXLIGA;
	IniTri(&TriIni);
	InitIncr(&IncrIni);

	alldck(&DCKxyz,&size);
	alldck(&DSTxyz,&size);

	fileop = nfil;

	nomemf = 0;
	filmem(0,0,dcklig,&fileop);

	iffset = 0;

	iatomsd = *(xyzp->iatoms);
	mxnatd = *(xyzp->mxnat);

/* get ambfor xyz file (gaff atom types */

	fftmp = *fftyp;

	ppcoo = xyzp->coo;
	ppanz = xyzp->ianz;
	ppatclr = xyzp->iatclr;

	xyzp->coo = DCKxyz.coo;
	xyzp->ianz = DCKxyz.ianz;
	xyzp->iatclr = DCKxyz.iatclr;

	gettnd_(&igttnk,&ZERO,&ipdbon,&iffset,&iheat,&heat,
	DCKxyz.ianz,DCKxyz.iconn,DCKxyz.iatclr,DCKxyz.ityp,DCKxyz.coo,
	DCKxyz.qat,DCKxyz.isurf);

	xyzp->coo = ppcoo;
	xyzp->ianz = ppanz;
	xyzp->iatclr = ppatclr;

	if (!igttnk) {
	   fprintf(stderr,"File %.200s is NOT [AMBFOR] format\n",dcklig);
	   return(0);
	}

	*fftyp = fftmp;
	DCKxyz.iatoms = &ndocka;
	*DCKxyz.iatoms = *(xyzp->iatoms);

	for (i=0; i < ndocka; i++) {
	   singleb.ityp[i] = ABS(DCKxyz.ityp[i]);
	   DCKxyz.ityp[i] = ABS(DCKxyz.ityp[i]);
	}

/* retype to sybyl atom types */

	pp = xyzp;
	xyzp = &DCKxyz;

	for (i=0; i < ndocka; i++) {

	   i1 = i + 1;
	   DCKxyz.iaton[i] = 2;
	   ispnd_(&irs,&i1,&irng,&ONE,&ONE,
	   DCKxyz.qat,DCKxyz.ianz,DCKxyz.iaton,DCKxyz.iconn,DCKxyz.lwrit,DCKxyz.lring);

	   strcpy(strname,elemts[DCKxyz.ianz[i]-1]);
	   strcat(strname,ATYPE[irs-1]);
	   singleb.irsd[i] = IHBT[irs-1];

	   ss = strname; 
	   if (strname[0] == ' ') ss++;

	   for (j=0; j < MXMOL2; j++) {
		if (strncmp(ss,mol2[j],5) == 0) DCKxyz.ityp[i] = j+1;
	   }
	}
	fileop = tmpfil;
	if (COO[istruct] != NULL) {
	    COO[istruct]->memfil = fileop;
	}
	
	xyzp = pp;

	*(xyzp->iatoms) = iatomsd;
	*(xyzp->mxnat)  = mxnatd;

	LIGCNT[0] = LIGCNT[1] = LIGCNT[2] = 0.0;

	for (i=0; i < ndocka; i++) {
	   for (j=0; j < 3; j++) {
		LIGCNT[j] = LIGCNT[j] + DCKxyz.coo[i*3+j];
	   }
	}

	for (j=0; j < 3; j++) {
	   LIGCNT[j] = LIGCNT[j] / (double) ndocka;
	}

	dmin = BIGD;
	LCNT = -1;
	for (i=0; i < ndocka; i++) {
	   dd = 0.0;
	   for (j=0; j < 3; j++) {
		tt = LIGCNT[j] - DCKxyz.coo[i*3+j];
		tt = tt * tt;
		dd = dd + tt;
	   }
	   if (dd < dmin) {
		dmin = dd;
		LCNT = i;
	   }
	}

	IniCHK();

	return(1);
}

void calind(int ires,int *indtmp)
{
   int i,j,k,l,indx;

   indx = *indtmp;

   if (calfptr->icalf[ires][1] != 0) {

   /* amide */

   IncrAll(&inttyp[indx]);

   for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[2]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = 
		xyzp->coo[(calfptr->icalf[ires][1]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[3]-1)*3+j]; 
   }
   inttyp[indx]->type = AMIDE;
   inttyp[indx]->area = AMID1;
   inttyp[indx]->res  = calfptr->irsnr[ires-1];
   inttyp[indx]->ires = ires;

   cal_area(inttyp[indx]);
   indx++;

   IncrAll(&inttyp[indx]);

   for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[2]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(calfptr->icalf[ires][1]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[3]-1)*3+j]; 
   }
   inttyp[indx]->type = AMIDE;
   inttyp[indx]->area = AMID2;
   inttyp[indx]->res  = calfptr->irsnr[ires-1];
   inttyp[indx]->ires = ires;

   cal_area(inttyp[indx]);
   indx++;
   }

   /* backbone C=O */

   IncrAll(&inttyp[indx]);

   for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[3]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[2]-1)*3+j]; 
   }
   inttyp[indx]->type = H_ACC;
   inttyp[indx]->area = CO;
   inttyp[indx]->res  = calfptr->irsnr[ires-1];
   inttyp[indx]->ires = ires;

   cal_area(inttyp[indx]);

   indx++;

   /* backbone NH */

   if ((ipdb[0] != 0 && ihpdb[0] != 0) && 
	calfptr->iamino[ires-1] != 15 ) {

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[0]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[0]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ihpdb[0]-1; 
	inttyp[indx]->atom[1] = ipdb[0]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;
   }

   switch (calfptr->iamino[ires-1]) {
   case 3:
   case 4:
   case 5:
   /* serine, threonine */
   /* serine, threonine OH */

        if (calfptr->iamino[ires-1] != 4) {

	   if ((calfptr->iamino[ires-1] == 3 && ihpdb[9] > 0) ||
	       (calfptr->iamino[ires-1] == 5 && ihpdb[12] > 0)) {
   		IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 3) {

			inttyp[indx]->c[0][j] = 
				xyzp->coo[(ihpdb[9]-1)*3+j]; 
			inttyp[indx]->c[1][j] = 
				xyzp->coo[(ipdb[30]-1)*3+j]; 

		   } else if (calfptr->iamino[ires-1] == 5) {

			inttyp[indx]->c[0][j] = 
				xyzp->coo[(ihpdb[12]-1)*3+j]; 
			inttyp[indx]->c[1][j] = 
				xyzp->coo[(ipdb[31]-1)*3+j]; 
		   }
		}
        	if (calfptr->iamino[ires-1] == 3) {
		   inttyp[indx]->atom[0] = ihpdb[9]-1; 
		   inttyp[indx]->atom[1] = ipdb[30]-1; 
		} else if (calfptr->iamino[ires-1] == 5) {
		   inttyp[indx]->atom[0] = ihpdb[12]-1; 
		   inttyp[indx]->atom[1] = ipdb[31]-1; 
		}

		inttyp[indx]->type = H_DON;
		inttyp[indx]->area = ONH;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;

   		IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 3) {
			inttyp[indx]->c[0][j] = 
				xyzp->coo[(ipdb[30]-1)*3+j]; 
			inttyp[indx]->c[1][j] = 
				xyzp->coo[(ipdb[4]-1)*3+j]; 
			inttyp[indx]->c[2][j] = 
				xyzp->coo[(ihpdb[9]-1)*3+j]; 
	   	   } else {
			inttyp[indx]->c[0][j] = 
				xyzp->coo[(ipdb[31]-1)*3+j]; 
			inttyp[indx]->c[1][j] = 
				xyzp->coo[(ipdb[4]-1)*3+j]; 
			inttyp[indx]->c[2][j] = 
				xyzp->coo[(ihpdb[12]-1)*3+j]; 
		   }
		}

		inttyp[indx]->type = H_ACC;
		inttyp[indx]->area = OSP3;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;

	   } else {
	        if (calfptr->iamino[ires-1] == 3) {
		   sprintf(cmdstr,
"Residue serine %d possibly covalently linked to ligand !!\n",
		   calfptr->irsnr[ires-1]);
		}
	        if (calfptr->iamino[ires-1] == 5) {
		   sprintf(cmdstr,
"Residue Threonine %d possibly covalently linked to ligand !!\n",
		   calfptr->irsnr[ires-1]);
		}
		return;
	   }

	} else {

   	   IncrAll(&inttyp[indx]);

	   for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[36]-1)*3+j]; 
	   }
	   inttyp[indx]->type = SULFUR;
	   inttyp[indx]->area = SPH2;
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);
   	   indx++;

	}

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
        if (calfptr->iamino[ires-1] != 5) {
	   inttyp[indx]->type = CH2;
	} else {
	   inttyp[indx]->type = CH;
	}
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

        if (calfptr->iamino[ires-1] == 5) {

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
	}
	inttyp[indx]->type = CH3;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
	}
	inttyp[indx]->type = PHE_CH3;
	inttyp[indx]->area = CH3_PHE;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	}

	break;
   case 1:
   case 2:
   case 6:
   case 7:
   case 11:
   /* glycine, alanine, isoleucine, leucine */

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
        if (calfptr->iamino[ires-1] != 1) {
	   inttyp[indx]->type = CH;
	} else {
	   inttyp[indx]->type = CH2;
	}
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

        if (calfptr->iamino[ires-1] >= 2) {
   /* Cbeta */
   	   IncrAll(&inttyp[indx]);

	   for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	   }
           if (calfptr->iamino[ires-1] == 9 || 
		calfptr->iamino[ires-1] == 11) {
		inttyp[indx]->type = CH2;
           } else if (calfptr->iamino[ires-1] > 2) {
		inttyp[indx]->type = CH;
	   } else {
		inttyp[indx]->type = CH3;
	   }
	   inttyp[indx]->area = SPH1;
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);
   	   indx++;

           if (calfptr->iamino[ires-1] == 2) {
   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
		}
		inttyp[indx]->type = PHE_CH3;
		inttyp[indx]->area = CH3_PHE;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;
	   }
	}

        if (calfptr->iamino[ires-1] >= 6) {
   /* Cgamma */

	   if (calfptr->iamino[ires-1] != 7 && ipdb[6] != 0) {
   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[6]-1)*3+j]; 
		}
        	if (calfptr->iamino[ires-1] > 6) {
		   inttyp[indx]->type = CH;
		} else {
		   inttyp[indx]->type = CH2;
		}
		inttyp[indx]->area = SPH1;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;
	   }

           if (calfptr->iamino[ires-1] == 6 || 
		calfptr->iamino[ires-1] == 7 ||
		calfptr->iamino[ires-1] == 11) {
		/* isoleucine cg2,cd1 and leucine cd1,cd2 */
		/* valine cg1,cg2 */

   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 6) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
		   } else if (calfptr->iamino[ires-1] == 11) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
		   } else {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[6]-1)*3+j]; 
		   }
		}
		inttyp[indx]->type = PHE_CH3;
		inttyp[indx]->area = CH3_PHE;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;

   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 6) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
		   } else if (calfptr->iamino[ires-1] == 11) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
		   } else {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[6]-1)*3+j]; 
		   }
		}
		inttyp[indx]->type = CH3;
		inttyp[indx]->area = SPH1;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;

   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 6) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
		   } else if (calfptr->iamino[ires-1] == 11) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
		   } else {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
		   }
		}
		inttyp[indx]->type = PHE_CH3;
		inttyp[indx]->area = CH3_PHE;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;

   	   	IncrAll(&inttyp[indx]);

		for (j=0; j<3; j++) {
		   if (calfptr->iamino[ires-1] == 6) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
		   } else if (calfptr->iamino[ires-1] == 11) {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
		   } else {
		      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[7]-1)*3+j]; 
		   }
		}
		inttyp[indx]->type = CH3;
		inttyp[indx]->area = SPH1;
        	inttyp[indx]->res  = calfptr->irsnr[ires-1];
        	inttyp[indx]->ires = ires;

		cal_area(inttyp[indx]);
   		indx++;
	   }
	}

	break;
   case 8:
   /* methionine */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	    inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[35]-1)*3+j]; 
	}
	inttyp[indx]->type = SULFUR;
	inttyp[indx]->area = SPH2;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[11]-1)*3+j]; 
	}
	inttyp[indx]->type = PHE_CH3;
	inttyp[indx]->area = CH3_PHE;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[11]-1)*3+j]; 
	}
	inttyp[indx]->type = CH3;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 9:
   /* asparate */
   /* OD1, CG, OD2 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[28]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[29]-1)*3+j]; 
	}
	inttyp[indx]->q0 = -0.5; 
	inttyp[indx]->q1 =  0.0; 
	inttyp[indx]->q2 = -0.5; 
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = COOmin;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);

   	indx++;

   /* OD2, CG, OD1 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[29]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[28]-1)*3+j]; 
	}
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = COOmin;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);

   	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 10:
   /* asparagine */
   /* ND2 HD21/HD22 */


   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   if (ihpdb[21] != 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[21]-1)*3+j]; 
	      inttyp[indx]->atom[0] = ihpdb[21]-1; 
	   } else if (ihpdb[25] != 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[25]-1)*3+j]; 
	      inttyp[indx]->atom[0] = ihpdb[25]-1; 
	   } else {
	      inttyp[indx]->c[0][j] = 0.0; 
	      inttyp[indx]->atom[0] = 0; 
	   }
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[20]-1)*3+j]; 
	}
	inttyp[indx]->atom[1] = ipdb[20]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   if (ihpdb[24] != 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[24]-1)*3+j]; 
	      inttyp[indx]->atom[0] = ihpdb[24]-1; 
	   } else if (ihpdb[26] != 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[26]-1)*3+j]; 
	      inttyp[indx]->atom[0] = ihpdb[26]-1; 
	   } else {
	      inttyp[indx]->c[0][j] = 0.0; 
	      inttyp[indx]->atom[0] = 0; 
	   }
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[20]-1)*3+j]; 
	}
	inttyp[indx]->atom[1] = ipdb[20]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[28]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = CO;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 12:
   /* Lysine */

	if (ihpdb[41] == 0) {
   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[26]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[11]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ihpdb[39]-1)*3+j]; 
	   inttyp[indx]->c[3][j] = xyzp->coo[(ihpdb[40]-1)*3+j]; 
	}
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = NAMINO;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;
	}

	/* hz_1 nz */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[39]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[26]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 1.0; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = NHP;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

	/* hz_2 nz */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[40]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[26]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 1.0; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = NHP;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

	/* hz_3 nz */

	if (ihpdb[41] != 0) {
   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[41]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[26]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 1.0; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = NHP;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;
	}

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cdelta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[8]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cepsilon */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[11]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 13:
   /* glutamate */
   /* OE1, CD, OE2 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[33]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[8]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[34]-1)*3+j]; 
	}
	inttyp[indx]->q0 = -0.5; 
	inttyp[indx]->q1 =  0.0; 
	inttyp[indx]->q2 = -0.5; 
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = COOmin;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* OE2, CD, OE1 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[34]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[8]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[33]-1)*3+j]; 
	}
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = COOmin;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 14:
   /* glutamine */
   /* NE2 HE21/HE22 */


   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[33]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[23]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ihpdb[33]-1; 
	inttyp[indx]->atom[1] = ipdb[23]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[34]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[23]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ihpdb[34]-1; 
	inttyp[indx]->atom[1] = ipdb[23]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	GLUTH[nglut] = indx;
//fprintf(stderr,"glutamin ONH %d\n",indx);
	cal_area(inttyp[indx]);
	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[33]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[8]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[33]-1; 
	inttyp[indx]->atom[1] = ipdb[8]-1; 
	inttyp[indx]->type = H_ACC;
	inttyp[indx]->area = CO;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

//fprintf(stderr,"glutamin CO %d\n",indx);
	GLUTCO[nglut] = indx;
	cal_area(inttyp[indx]);
	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[1]-1; 
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[4]-1; 
	inttyp[indx]->type = CH;
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[5]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	nglut++;

	break;
   case 15:
   /* Proline */
   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[1]-1; 
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[4]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[5]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cdelta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[8]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[8]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 16:
   /* Arginine */
   /* ne-he */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[27]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[21]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 0.333; 
	inttyp[indx]->atom[0] = ihpdb[27]-1; 
	inttyp[indx]->atom[1] = ipdb[21]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* nh1-hh11 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[54]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[24]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 0.333; 
	inttyp[indx]->atom[0] = ihpdb[54]-1; 
	inttyp[indx]->atom[1] = ipdb[24]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* nh1-hh12 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[55]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[24]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 0.333; 
	inttyp[indx]->atom[0] = ihpdb[55]-1; 
	inttyp[indx]->atom[1] = ipdb[24]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* nh2-hh21 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[57]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[25]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 0.333; 
	inttyp[indx]->atom[0] = ihpdb[57]-1; 
	inttyp[indx]->atom[1] = ipdb[25]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* nh2-hh22 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[58]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[25]-1)*3+j]; 
	}
	inttyp[indx]->q0 = 0.0; 
	inttyp[indx]->q1 = 0.333; 
	inttyp[indx]->atom[0] = ihpdb[58]-1; 
	inttyp[indx]->atom[1] = ipdb[25]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[1]-1; 
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[4]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->atom[0] = ipdb[5]-1; 
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 17:
   /* Histidine */

	if ((ihpdb[21] != 0 && ihpdb[33] != 0) ||
		(ihpdb[21] != 0 && ihpdb[33] == 0)) {

   	   IncrAll(&inttyp[indx]);


	   for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[21]-1)*3+j]; 
		inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[19]-1)*3+j]; 
	   }
	   if (ihpdb[21] != 0 && ihpdb[33] != 0) {
		inttyp[indx]->type = H_DON;
		inttyp[indx]->area = NHP;
	   } else {
		inttyp[indx]->atom[0] = ihpdb[21]-1; 
		inttyp[indx]->atom[1] = ipdb[19]-1; 
		inttyp[indx]->type = H_DON;
		inttyp[indx]->area = ONH;
	   }
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);
	   indx++;

	}

	if ((ihpdb[21] != 0 && ihpdb[33] != 0) ||
		(ihpdb[33] != 0 && ihpdb[21] == 0)) {

   	   IncrAll(&inttyp[indx]);

	   for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[33]-1)*3+j]; 
		inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[23]-1)*3+j]; 
	   }
	   if (ihpdb[21] != 0 && ihpdb[33] != 0) {
		inttyp[indx]->type = H_DON;
		inttyp[indx]->area = NHP;
	   } else {
		inttyp[indx]->atom[0] = ihpdb[33]-1; 
		inttyp[indx]->atom[1] = ipdb[33]-1; 
		inttyp[indx]->type = H_DON;
		inttyp[indx]->area = ONH;
	   }
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);
	   indx++;
	}

	if (ihpdb[21] == 0 || ihpdb[33] == 0) {

   	   IncrAll(&inttyp[indx]);

	   for (j=0; j<3; j++) {
	     if (ihpdb[21] == 0) {
		/* HIE */
		inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[19]-1)*3+j]; 
		inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
		inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	     } else {
		/* HID */
		inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[23]-1)*3+j]; 
		inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
		inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	     }
	   }

	   inttyp[indx]->type = H_ACC;
	   inttyp[indx]->area = NARYL;
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);

	   indx++;
	}

   /* Calpha */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cbeta */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* Cgamma */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* CE1 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   /* CD2 */

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 18:
   case 19:
   /* phenylalanine, tyrosine */

        if (calfptr->iamino[ires-1] == 19) {

	   /* OH */

   	   IncrAll(&inttyp[indx]);

	   for (j=0; j<3; j++) {
		inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[51]-1)*3+j]; 
		inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[32]-1)*3+j]; 
	   }
	   inttyp[indx]->atom[0] = ihpdb[51]-1; 
	   inttyp[indx]->atom[1] = ipdb[32]-1; 
	   inttyp[indx]->type = H_DON;
	   inttyp[indx]->area = ONH;
           inttyp[indx]->res  = calfptr->irsnr[ires-1];
           inttyp[indx]->ires = ires;

	   cal_area(inttyp[indx]);
   	   indx++;

	}

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_CENTER;
	inttyp[indx]->area = PHC1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_CENTER;
	inttyp[indx]->area = PHC2;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[12]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[16]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   case 20:
   /* tryptofan */


   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   if (ihpdb[29] > 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[29]-1)*3+j]; 
	   } else if (ihpdb[31] > 0) {
	      inttyp[indx]->c[0][j] = xyzp->coo[(ihpdb[31]-1)*3+j]; 
	   }
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[22]-1)*3+j]; 
	}
	if (ihpdb[29] > 0) {
	   inttyp[indx]->atom[0] = ihpdb[29]-1; 
	} else if (ihpdb[31] > 0) {
	   inttyp[indx]->atom[0] = ihpdb[31]-1; 
	}
	inttyp[indx]->atom[1] = ipdb[22]-1; 
	inttyp[indx]->type = H_DON;
	inttyp[indx]->area = ONH;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[14]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[17]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_CENTER;
	inttyp[indx]->area = PHC1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[14]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[18]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_CENTER;
	inttyp[indx]->area = PHC2;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[18]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[14]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[15]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[15]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[18]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[17]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[17]-1)*3+j]; 
	   inttyp[indx]->c[1][j] = xyzp->coo[(ipdb[15]-1)*3+j]; 
	   inttyp[indx]->c[2][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	}
	inttyp[indx]->type = PHENYL_RING;
	inttyp[indx]->area = PHR;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[1]-1)*3+j]; 
	}
	inttyp[indx]->type = CH;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[4]-1)*3+j]; 
	}
	inttyp[indx]->type = CH2;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[5]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[9]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[10]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[13]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[14]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[17]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[18]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

   	IncrAll(&inttyp[indx]);

	for (j=0; j<3; j++) {
	   inttyp[indx]->c[0][j] = xyzp->coo[(ipdb[15]-1)*3+j]; 
	}
	inttyp[indx]->type = ARO;
	inttyp[indx]->area = SPH1;
        inttyp[indx]->res  = calfptr->irsnr[ires-1];
        inttyp[indx]->ires = ires;

	cal_area(inttyp[indx]);
   	indx++;

	break;
   }
   *indtmp = indx;
}

void CreateEstr()
{
  int ligselp,n;
  char Dev[10] = "      ";
  char FAST[4] = "  ";
  char DEB[5] = "    ";
  char METHOD[7] = "      ";
  char HETA[7] = "      ";
  char xyzFile[30] = "                        ";
  char NSOL[9] = "        ";
  char TOTAL[1065];
  char filen[200];
  FILE *fout;

  sprintf(xyzFile," -r %-s ",dcklig);
  
  if (DCKdev > 0.65) {
     sprintf(Dev,"-V %3.2f ",DCKdev);
  }

  if (!FASTSLOW) {
     sprintf(FAST,"-q ");
  } else {
     sprintf(FAST,"  ");
  }

  if (debugdck) {
     sprintf(DEB,"-d ");
  } else {
     sprintf(DEB," ");
  }

  if (DCKMETH) {
     sprintf(METHOD,"-m 1 ");
  }

  if (!DCKMETH) {
     ligselp = LigSel - 1 - 4;
     sprintf(HETA,"-h %1d ",ligselp);
  }

  if (dcksol != 20) {
     sprintf(NSOL,"-n %-3d ",dcksol);
  }

  strcpy(TOTAL,molden_root);
  strcat(TOTAL,"/bin/docker"); 
  strcat(TOTAL,xyzFile); 
  if (dcksol != 20) strcat(TOTAL,NSOL); 
  strcat(TOTAL,HETA); 
  if (DCKdev > 0.65) strcat(TOTAL,Dev); 
  strcat(TOTAL,DEB); 
  if (!FASTSLOW) strcat(TOTAL,FAST); 
  if (DCKMETH) strcat(TOTAL,METHOD); 	// this is NOT executed !!
  strcat(TOTAL,pdbFile); 
  strcat(TOTAL," > log"); 
  n = strlen(TOTAL);

// we have to get the 'dcklig' file to open !!
  fprintf(stderr,"execution string: %.69s\n",TOTAL);
}

void parseopt_()
{
  int ligselp,n;
  int len,ierr;
  char line[1000];
  char *nxtlin;
  FILE *fout;

  fout = fopen("docker.inp","r");

  dcklig = (char *) malloc(sizeof(char)*(100));
  fgets(dcklig,100,fout);
  nxtlin = strchr(dcklig,'\n');
  nxtlin[0] = '\0';

  pdbcode = (char *) malloc(sizeof(char)*(100));
  fgets(pdbcode,100,fout);	// "3erd"
  nxtlin = strchr(pdbcode,'\n');
  nxtlin[0] = '\0';
  pdbFile = (char *) malloc(sizeof(char)*(100));
  strcpy(pdbFile,pdbcode);
  strcat(pdbFile,".pdb");

  fgets(line,100,fout);
  if (line[0] != 32) {
     sscanf(line,"%d",&dcksol);
  }
  fgets(line,100,fout);
  if (line[0] != 32) {
     sscanf(line,"%d",&ligselp);
     LigSel = ligselp + 5;
  }
  fgets(line,100,fout);
  if (line[0] != 32) {
     sscanf(line,"%f",&DCKdev);
  }
  fgets(line,100,fout);
  if (strncmp(line,"-d",2) == 0) {
     debugdck = 1;
  }
  fgets(line,100,fout);
  if (strncmp(line,"-q",2) == 0) {
     FASTSLOW = 0;
  } else {
     FASTSLOW = 1;
  }
  fgets(line,100,fout);
  if (line[0] == 49) {
     DCKMETH = 1;
  }
  fclose(fout);

  CreateEstr();

  if (access("docker.inp",F_OK) == 0) {
      unlink("docker.inp");
  }

  clfort_();

  fniun->iun2 = 49;
  len = strlen(pdbFile);
  openfil_(&FOURTYNINE,pdbFile,&len,&ONE,&ONE,&ZERO,&ierr);

}

void dodck_()
{
    int len,ierr;

// we have to get DCKMETH from the commandline and the same for LigSel
// print the string for ligsel to confirm to the user

    if (DCKMETH == 0) {
	ProcProtLig(LigSel);
    } else {
	ProcProt();
    }

    if (dcklig == NULL) {
	prtflg_();
	exit(-1);
    }

    SetupTable();

    clfort_();

    fniun->iun2 = 47;

    len = strlen(dcklig);
    openfil_(&FOURTYSEVEN,dcklig,&len,&ONE,&ONE,&ZERO,&ierr);

    if (!GetLig()) {
	return;
    }
    clfort_();

    ProcLig(1);

    clfort_();

    fniun->iun2 = 77;
    clfort_();

}

void ProcProtLig(int iop)
{

    int i,j,k,l,m,n,ires,irest,indx,iheta,SelRes,size;
    int frst,hfrst,ifrst,ihfrst;
    float tt,dd;

    if (DCKMETH == 1) {
       if (DCKRadius*toangs > 8.0) DCKRadius = 8.0/toangs;
    } else {
       DCKRadius = 3.5/toangs;
    }

    if (*ipdbon && calfptr->ncalf == 0) return;

    for (i=0; i< NUMCAL; i++) {
	resinc[i] = 0;
    }

    size = MXLIGA;

    alldck(&DCKxyz,&size);

    SelRes = -1*iop;

    if (xyzp->iclos == NULL) {
	if ((xyzp->iclos = (int *) malloc((sizeof i)*NUMAT)) == NULL) {
	   fprintf(stderr,"NOT enough memory to allocate iclos array !\n");
	}
    }

    iheta = 0; frst = 1; hfrst = 1; ifrst = -1; ihfrst = -1;

    for (i=0;i < *xyzp->iatoms; i++ ) {
	xyzp->iclos[i] = 0;
	if (xyzp->iresid[i] == SelRes+1) {
	   if (frst) {
		ifrst = i;
		frst = 0;
	   }
	   if (xyzp->ianz[i] == 1) {
	      if (hfrst) {
		ihfrst = i;
		hfrst = 0;
	      }
	   }
	   for (j=0; j<3; j++) {
		DCKxyz.coo[iheta*3+j] = xyzp->coo[i*3+j];
	   }
	   DCKxyz.ianz[iheta] = xyzp->ianz[i];
	   xyzp->iaton[iheta] = 1;
	   DCKxyz.iconn[iheta*(MXCON+1)] = xyzp->iconn[i*(MXCON+1)];
	   for (j=0; j<xyzp->iconn[i*(MXCON+1)]; j++) {
	       m = xyzp->iconn[i*(MXCON+1)+j+1] - 1;
	       if (xyzp->ianz[m] == 1) {
           	  DCKxyz.iconn[iheta*(MXCON+1)+j+1] = 
			xyzp->iconn[i*(MXCON+1)+j+1] - (ifrst - ihfrst) + 1;
	       } else {
           	  DCKxyz.iconn[iheta*(MXCON+1)+j+1] = 
			xyzp->iconn[i*(MXCON+1)+j+1] - ifrst;
	       }
	   }
	   iheta++;
	}
    }

    ndocka = iheta;

    NCLOS = 0;
    for (k=0; k<ndocka; k++) {
	for (ires = 1; ires < calfptr->ncalf+1; ires++ ) {

   	   getpdb_(&ires,ipdb,ihpdb);

	   for (i=0; i<MXSYM; i++) {
		dd = 0.0;
		if (ipdb[i] > 0) {
	   	   for (j=0; j<3; j++) {
			tt = ((float) xyzp->coo[(ipdb[i]-1)*3+j] - 
				DCKxyz.coo[k*3+j]);
			dd = dd + tt*tt;
		   }
		   if (sqrt(dd) < DCKRadius) {
		      resinc[ires-1] = 1;
		      if (ipdb[i]-1 >= 0) {
			if (xyzp->iclos[ipdb[i]-1] == 0) {
			   xyzp->iclos[ipdb[i]-1] = 1;
			   NCLOS++;
			}
		      }
		   }
		}
	   }

	   for (i=0; i<3*MXHSYM; i++) {
		dd = 0.0;
		if (ihpdb[i] > 0) {
	   	   for (j=0; j<3; j++) {
			tt = ((float) xyzp->coo[(ihpdb[i]-1)*3+j] - 
				DCKxyz.coo[k*3+j]);
			dd = dd + tt*tt;
		   }
		   if (sqrt(dd) < DCKRadius) {
			resinc[ires-1] = 1;
		        if (ihpdb[i]-1 >= 0) {
			   if (xyzp->iclos[ihpdb[i]-1] == 0) {
				xyzp->iclos[ihpdb[i]-1] = 1;
				NCLOS++;
			   }
			}
		   }
		}
	   }

	}
    }

    n = 0;
    for (i=0;i < *xyzp->iatoms; i++ ) {
	if (xyzp->iclos[i] == 1) {
	   for (j=0;j < 3; j++ ) {
		DCKCNT[j] = DCKCNT[j] + xyzp->coo[i*3+j];
	   }
	   n++;
	}
    }

    if (n != 0) {
	for (j=0;j < 3; j++ ) {
	   DCKCNT[j] = DCKCNT[j]/(double)n;
	}
    }
    
    indx = 0;
    for (ires = 0; ires < calfptr->ncalf; ires++ ) {
	irest = ires + 1;
	if (resinc[ires]) {
   	   getpdb_(&irest,ipdb,ihpdb);
	   calind(irest,&indx);
	}
    }

    ndocka = 0;
    nintp = indx;
}

void ProcProt()
{
    int i,j,k,l,ic,ires,indx,clss,doit,irest;
    float tmp1[3],tmp3[3],C1[3],C2[3],C3[3],tt,dd;
    double colv[3];
    double roddef;

    if (DCKRadius*toangs > 8.0) DCKRadius = 8.0/toangs;

    if (*ipdbon && calfptr->ncalf != 0) {
	indx = 0;
	for (ires = 1; ires < calfptr->ncalf+1; ires++ ) {

	   doit = 0;

   	   getpdb_(&ires,ipdb,ihpdb);

	   for (i=0; i<MXSYM; i++) {
		dd = 0.0;
		if (ipdb[i] > 0) {
	   	   for (j=0; j<3; j++) {
			tt = ((float) xyzp->coo[(ipdb[i]-1)*3+j] - CNTDCK[j]);
			dd = dd + tt*tt;
		   }
		   if (sqrt(dd) < DCKRadius) doit = 1;
		}
	   }

	   for (i=0; i<3*MXHSYM; i++) {
		dd = 0.0;
		if (ihpdb[i] > 0) {
	   	   for (j=0; j<3; j++) {
			tt = ((float) xyzp->coo[(ihpdb[i]-1)*3+j] - CNTDCK[j]);
			dd = dd + tt*tt;
		   }
		   if (sqrt(dd) < DCKRadius) doit = 1;
		}
	   }

	   if (doit) {
 		irest = ires + 1;
		calind(ires,&indx);
	   }
	}
    }

    nintp = indx;
    DCKPROTPROC = 1;
}

void parstr_(str, iopt)

char *str;
int *iopt;
{
       switch(*iopt) {
       case 11: 
	  pdbcode = (char *) malloc(6);
	  strncpy(pdbcode,str,4);
	  pdbcode[5] = '\0';
	  break;
       case 13: 
	  tmpfil = str;
	  break;
       case 14:
	  mldfile = str;
	  break;
       }
}

void typamb_(ipdb,jres,ihpdb,ihashy)
int *ipdb;
int *ihpdb;
int *jres;
int *ihashy;
{

	typamd_(ipdb,jres,ihpdb,ihashy,xyzp->ianz,xyzp->iconn,xyzp->ityp); 
}

void setchg_(iat,iopt)
int *iat;
int *iopt;
{

	setchd_(iat,iopt,xyzp->qat,xyzp->ityp);

}

void chkbrk_()
{
	chkbrd_(
	xyzp->iconn,calfptr->icalf,calfptr->ianf,calfptr->islu,
	calfptr->iamino,calfptr->isal,calfptr->reson,
	&calfptr->ncalf,&calfptr->nchain);
}

void xyzcoo_(idocopy,idoconv,ioadd)
int *idocopy;
int *idoconv;
int *ioadd;
{

	xyzcod_(idocopy,idoconv,ioadd,xyzp->ianz,xyzp->coo);

}

void gettyp_(ires,iat1,iat2)
int *ires;
int *iat1;
int *iat2;
{
	gettyd_(ires,iat1,iat2,
	xyzp->ityp,xyzp->ipdbt,xyzp->ianz,xyzp->iresid,
	calfptr->iamino,calfptr->icalf,&calfptr->ncalf);
}

void parfns_(str, nstr)
char *str;
int *nstr;
{

   if (*nstr < MAXSTRLEN) {
       strcp(str,strname,*nstr);
       strname[*nstr] = '\0';
   }

}

void calfa_(istat,istpdb,iaddh)
int *istat;
int *istpdb;
int *iaddh;
{

	calfd_(istat,istpdb,iaddh,
	xyzp->ianz,xyzp->iconn,xyzp->ityp,
        calfptr->icalf,&calfptr->ncalf,calfptr->ianf,calfptr->islu,
	&calfptr->nchain,calfptr->iamino,
	calfptr->isal,calfptr->irsnr,&calfptr->ihashb);

}

void addhs_(ires,jres,ipdb,ihpdb,nterm)
int *ires;
int *jres;
int *ipdb;
int *ihpdb;
int *nterm;
{

	addhd_(ires,jres,ipdb,ihpdb,nterm,
	xyzp->ianz,xyzp->iaton,xyzp->iatclr,xyzp->iresid,xyzp->iconn,
	xyzp->isurf,xyzp->ipdbt,xyzp->ityp,&calfptr->ncalf,calfptr->icalf,
	xyzp->coo);

}

void hcoord_(iaddh)
int *iaddh;
{
  int istat;

	hcoodd_(&istat,iaddh,
	xyzp->ipdbt,xyzp->coo,xyzp->ianz,xyzp->iaton,xyzp->iresid,xyzp->iconn,
	calfptr->icalf,&calfptr->ncalf,calfptr->ianf,calfptr->islu,
	&calfptr->nchain,calfptr->iamino);


	if (!istat) {
	   allcoo_(&addat,&ZERO);
	   hcoodd_(&istat,iaddh,
	   xyzp->ipdbt,xyzp->coo,xyzp->ianz,xyzp->iaton,xyzp->iresid,
	   xyzp->iconn,
	   calfptr->icalf,&calfptr->ncalf,calfptr->ianf,calfptr->islu,
	   &calfptr->nchain,calfptr->iamino);
        }
}

void bckok_(ibckok,ires,iop)
int *ibckok;
int *ires;
int *iop;
{

	bckod_(ibckok,ires,iop,
	xyzp->ianz,xyzp->iresid,xyzp->ipdbt,
	calfptr->iamino);

}

void typeit_(ipdb,jres,ihpdb,ihashy)
int *ipdb;
int *ihpdb;
int *jres;
int *ihashy;
{

	typeid_(ipdb,jres,ihpdb,ihashy,
	xyzp->ianz,xyzp->iconn,xyzp->ityp);

}

void CreateNPos(c1,c2,c3,c4)
double c1[3],c2[3],c3[3],c4[3];
{
  double v3[3],v4[3],vect[3];
  double c5[3],c6[3];
  double v21[3],v31[3];
  double cosa,sina;
  double angrad,fact,tot;
  int i;

// c1 == (C)=O	CD
// c2 == C=(O)	OE2
// c3 == NE2	NE2

  vsubd(c2,c1,v21);
  vsubd(c3,c1,v31);

  normalize(v21);
  normalize(v31);

// v3 perpendicular to C=O (v21) and N-C (v31)

  crossprd(v21,v31,v3);

// v4 perpendicular to C=O (v21) and v3

  crossprd(v21,v3,v4);

  angrad = (114.5 * PI) / 180.0;

  sina = sin(angrad);
  cosa = cos(angrad);

  fact = 2.763/toangs;

  for (i=0; i < 3; i++) {
	v4[i] = -v4[i];
  }

  normalize(v4);

  for (i=0; i < 3; i++) {
	vect[i] = -cosa*v21[i] + sina*v4[i];
  }

  normalize(vect);

  for (i=0; i < 3; i++) {
	vect[i] = fact*vect[i];
  }

// vect has the wrong direction

  for (i=0; i < 3; i++) {
//	c4[i] = (c2[i] + vect[i])*toangs;
	c4[i] = (c2[i] + vect[i]);
  }

// c4 is the projected N coordinate
}

void CreateCPos(c1,c2,c3,c4)
double c1[3],c2[3],c3[3],c4[3];
{
  double v3[3],v4[3],vect[3];
  double c5[3],c6[3];
  double v21[3],v31[3];
  double cosa,sina;
  double angrad,fact,tot;
  int i;

// c1 = NE2
// c2 = HE2
// c3 = (C)=O CD

  vsubd(c2,c1,v21);
  vsubd(c3,c1,v31);

  normalize(v21);
  normalize(v31);

// v3 perpendicular to N-H (v21) and C-N (v31)

  crossprd(v21,v31,v3);

// v4 perpendicular to N-H (v21) and v3

  crossprd(v21,v3,v4);

  angrad = (157.86 * PI) / 180.0;

  sina = sin(angrad);
  cosa = cos(angrad);

  fact = 2.7203/toangs;

  for (i=0; i < 3; i++) {
	v4[i] = -v4[i];
  }

  normalize(v4);

  for (i=0; i < 3; i++) {
	vect[i] = -cosa*v21[i] + sina*v4[i];
  }

  normalize(vect);

  for (i=0; i < 3; i++) {
	vect[i] = fact*vect[i];
  }

// vect has the wrong direction

  for (i=0; i < 3; i++) {
//	c4[i] = (c2[i] + vect[i])*toangs;
	c4[i] = (c2[i] + vect[i]);
  }

//  fprintf(stderr,"coordinates %7.3f %7.3f %7.3f\n",c4[0],c4[1],c4[2]);
// c4 is the projected C(=O) coordinate

}

