// to be implemented by each subclass
 public abstract Tuple<WeightVectorChromosome, WeightVectorChromosome> Crossover(WeightVectorChromosome parent2, Random random);
        // Crossover two chromosomes
        public override Tuple<WeightVectorChromosome, WeightVectorChromosome> Crossover(WeightVectorChromosome otherChromosome, Random random)
        {
            int crossoverPoint = random.Next(1, CHROMOSOME_LENGTH);
            if (crossoverPoint == 1)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 2)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 3)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 4)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 5)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 6)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }
            else if (crossoverPoint == 7)
            {
                WeightVectorChromosomeAll child1 = new WeightVectorChromosomeAll(((WeightVectorAll)this.chromosome).Corner, ((WeightVectorAll)this.chromosome).Empty_cells,
                    ((WeightVectorAll)this.chromosome).Highest_tile, ((WeightVectorAll)this.chromosome).Monotonicity, ((WeightVectorAll)this.chromosome).Points,
                    ((WeightVectorAll)this.chromosome).Smoothness, ((WeightVectorAll)this.chromosome).Snake, ((WeightVectorAll)otherChromosome.chromosome).Trapped_penalty);
                WeightVectorChromosomeAll child2 = new WeightVectorChromosomeAll(((WeightVectorAll)otherChromosome.chromosome).Corner, ((WeightVectorAll)otherChromosome.chromosome).Empty_cells,
                    ((WeightVectorAll)otherChromosome.chromosome).Highest_tile, ((WeightVectorAll)otherChromosome.chromosome).Monotonicity, ((WeightVectorAll)otherChromosome.chromosome).Points,
                    ((WeightVectorAll)otherChromosome.chromosome).Smoothness, ((WeightVectorAll)otherChromosome.chromosome).Snake, ((WeightVectorAll)this.chromosome).Trapped_penalty);
                return new Tuple<WeightVectorChromosome, WeightVectorChromosome>(child1, child2);
            }

            else throw new Exception();
        }