Exemplo n.º 1
0
void population::iterate(void)
{
//	GENO_TYPE kiddies[pop_size_];

	// Check for lack of improvement in best particle (over 25 iterations, then stop processing)
	if (fitness_calculation_counter_ > (best_in_swarm_.calced + (pop_size_ * gen_limit_)) )
		return;

	uint64_t iter, jter;

	for (iter=0; iter<pop_size_; iter++)
	{
		for (jter=0; jter<NUMBER_ATTRIBUTES; jter++)
		{
			pop_[iter].cc.vel[jter] =	(pop_[iter].cc.vel[jter] * inertia_)
				+ ( (rudi_.uniform((double)0.0,(double)1.0) * cog_) * (pop_[iter].bc.pos[jter]     - pop_[iter].cc.pos[jter]) )
				+ ( (rudi_.uniform((double)0.0,(double)1.0) * soc_) * (best_in_swarm_.cc.pos[jter] - pop_[iter].cc.pos[jter]) );

//			pop_[iter].cc[jter].vel = (pop_[iter].cc[jter].vel * inertia_) + (pop_[iter].cc[jter].vel * cog_) + (best_in_swarm_[jter].vel * soc_);
			if (pop_[iter].cc.vel[jter] > max_.vel[jter])
				pop_[iter].cc.vel[jter] = max_.vel[jter];
			else if (pop_[iter].cc.vel[jter] < min_.vel[jter])
				pop_[iter].cc.vel[jter] = min_.vel[jter];

//			pop_[iter].cc.pos[jter] = pop_[iter].cc.pos[jter] + (pop_[iter].cc.vel[jter] * 1.0);//time__);
//			if (pop_[iter].cc.pos[jter] > max_.pos[jter])
//				pop_[iter].cc.pos[jter] = max_.pos[jter];
//			else if (pop_[iter].cc.pos[jter] < min_.pos[jter])
//				pop_[iter].cc.pos[jter] = min_.pos[jter];

/*
			// discretization
			if ( rudi_.uniform((double)0.0,(double)1.0) < (double)( 1.0/ (1.0+exp(pop_[iter].cc.vel[jter] * -1.0)) ) )
			{
				pop_[iter].cc.pos[jter] = 1.0;
				pop_[iter].gen[jter] = 1;
			}
			else
			{
				pop_[iter].cc.pos[jter] = 0.0;
				pop_[iter].gen[jter] = 0;
			}
*/
		}
		discretize(pop_[iter]);
//		pop_[iter].gen = discretize(pop_[iter].cc);
		pop_[iter].fit = calcFitness(pop_[iter].gen);
		pop_[iter].calced = fitness_calculation_counter_;

		if (pop_[iter].fit > pop_[iter].bf)
		{
			pop_[iter].bc = pop_[iter].cc;
			pop_[iter].bf = pop_[iter].fit;
		}
//		cout << "ID: " << iter << "\tGEN: " << pop_[iter].gen << endl;
	}

	generation_++;
	bestest();
}
Exemplo n.º 2
0
//Runs the genetic algorithm
void Solver::runAStar()
{
    for(int i=0;i<gateLimit;++i)
    {
        circuits.push_back(Circuit());
    }
    bool go = true;
    int loc = -1;
    unsigned long long int generation=0;
    do
    {
        //algorithm adds new random gate every generation, and reverts if the fitness value goes lower
        ++generation;
        addGatesAstar();
        calcFitness();
        revert();
        runSortFitness();
        cull();
        loc = checkSolution();
        if(generation%1000 == 0)
        {
            cout<<"Generation: "<<generation<<"\n";
            cout<<"Num Gates:  "<<circuits[0].getGateNum()<<"\n";
        }
        if(loc != -1)
        {
            solutionLoc = loc;
            cout<<"Generation: "<<generation<<"\n";
            go = false;
        }
    }while(go);
}
Exemplo n.º 3
0
// Calculates the stats for k. Useful for human-readable output.
int calcFitnessDirect(Keyboard *k)
{
	calcFitness(k); // Otherwise, k->fitness, k->fingerUsage, and k->fingerWork 
	                // would not get assigned properly.

	int i;
	k->distance		= 0;
	k->inRoll		= 0;
	k->outRoll		= 0;
	k->sameHand		= 0;
	k->sameFinger	= 0;
	k->rowChange	= 0;
	k->homeJump		= 0;
	k->ringJump     = 0;
	k->toCenter		= 0;
	k->toOutside	= 0;

	for (i = 0; i < diLen; ++i) scoreDigraphDirect(k, diKeys[i], diValues[i]);

	for (i = 0; i < monLen; ++i) { 
		k->distance += trueDistance[locWithoutShifted(k, monKeys[i])] * (monValues[i] / 100); // meters 
	}
	
	return 0;
}
/**
*	calculates the fitness value
*/
void Physics::calcFitness(fitnessTest test, float* fit){
	switch(test){
	case move:
		{
			*fit= fitMove();
		}
		break;
	case iterateMove:
		{
			*fit +=fitMove2();
		}
		break;
	case dwarfslayerMove:
		{
			if(noBoxes<3){*fit = -999999;dead=true; totaltime=simulationTime;}
			else{*fit +=fitMove2();}
		}
		break;
	case fatLovingMove:
		{
			float totMass = 0;
			btCollisionObjectArray objs = m_dynamicsWorld->getCollisionObjectArray();
			for (int i = 1; i <= noBoxes; i++){
				totMass += 1.f/(float)((btRigidBody*) objs.at(i))->getInvMass();
			}
			*fit +=(fitMove2()*totMass/DensityHuman);
		}
		break;
	case boxLovingMove:
		{
			*fit +=fitMove2()*(float)noBoxes;
		}
		break;
	case jump:
		{
			*fit=max(fitJump(),*fit);
		}
		break;
	case combi:
		{
			clearFitnessFunctions();
			addFitnessFunction(jump,1);
			addFitnessFunction(move,1);
			calcFitness();
			return;
		}
		break;
	case none:
		*fit=0;

		break;
#ifdef _DEBUG
	default:

		printf("unkown fitness test\n");
#endif
	}
	*fit= floorf((*fit) * 10000 + 0.5) / 10000;
}
Exemplo n.º 5
0
int runTimingTests()
{
	time_t start, startsec;
	int i, j;
	Keyboard tester;
	Keyboard array[1024];
	
	long initAverage = 0;
	long copyAverage = 0;
	long fitnessAverage = 0;
	long locAverage = 0;
	
	struct timeval tv;
		
	/* Use a longer loop to get more accurate data. */
	for (j = 0; j < 50; j++) {
		// How long does it take to initialize a keyboard?
		gettimeofday(&tv, NULL);
		start = tv.tv_usec;
		startsec = tv.tv_sec;
		for (i = 0; i < 100000; ++i) initKeyboard(&tester);
		gettimeofday(&tv, NULL);
		initAverage = ((initAverage * j) + tv.tv_usec - start + 1000000*(tv.tv_sec - startsec)) / (j + 1);
		
		// How long does it take to copy a keyboard?
		gettimeofday(&tv, NULL);
		start = tv.tv_usec;
		startsec = tv.tv_sec;
		for (i = 0; i < 100000; ++i) copyKeyboard(&tester, &array[0]);
		gettimeofday(&tv, NULL);
		copyAverage = ((copyAverage * j) + tv.tv_usec - start + 1000000*(tv.tv_sec - startsec)) / (j + 1);

		// How long does it take to score a keyboard?
		gettimeofday(&tv, NULL);
		start = tv.tv_usec;
		startsec = tv.tv_sec;
		for (i = 0; i < 100000; ++i) calcFitness(&tester);
		gettimeofday(&tv, NULL);
		fitnessAverage = ((fitnessAverage * j) + tv.tv_usec - start + 1000000*(tv.tv_sec - startsec)) / (j + 1);

		// How long does it take to find a key on a keyboard?
		gettimeofday(&tv, NULL);
		start = tv.tv_usec;
		startsec = tv.tv_sec;
		for (i = 0; i < 100000; ++i) locIgnoreShifted(&tester, 'a');
		gettimeofday(&tv, NULL);
		locAverage = ((locAverage * j) + tv.tv_usec - start + 1000000*(tv.tv_sec - startsec)) / (j + 1);
	}
	printf(" *  Time to initialize 100,000 keyboards:     %ld microseconds.\n", initAverage);
	printf(" *  Time to copy 100,000 keyboards:           %ld microseconds.\n", copyAverage);
	printf(" *  Time to score 100,000 keyboards:          %ld microseconds.\n", fitnessAverage);
	printf(" *  Time to do locW/OShifted() 100,000 times: %ld microseconds.\n", locAverage);
	
	return 0;
}
void Physics::calcFitness(){
	float tmpFitness=1;
	for(int i=0;i<tests.size();i++){
		calcFitness(tests.at(i).type,&tests.at(i).value);
		if(dead){
			fitness= -999999;
			return;
		}
		tmpFitness*=tests.at(i).value*tests.at(i).weight+1;
	}
	fitness=max(tmpFitness-1, fitness);
}
Exemplo n.º 7
0
/* WARNING: Deprecated. Does not work with shifted characters.
 */
int bestSwap(Keyboard *k)
{
    printPercentages(k);

    calcFitness(k);
    int64_t fitness = k->fitness;
    int64_t origFitness = fitness;
    int64_t bestFitness = fitness;
    int bestIndices[2];
    Keyboard bestKeyboard = *k;

    int i, j;
    for (i = 0; i < trueksize; i++) {
        for (j = i+1; j < trueksize; j++) {
            if (!isLegalSwap(k, indices[i], indices[j]))
                continue;

            swap(k, indices[i], indices[j]);
            calcFitness(k);

            if (k->fitness < bestFitness) {
                bestFitness = k->fitness;
                bestKeyboard = *k;
                bestIndices[0] = indices[i];
                bestIndices[1] = indices[j];
            }

            /* Print out all swaps that are a certain percentage better. */
            if ((origFitness - k->fitness) / ((double) origFitness) > 0.05) {
                printPercentages(k);
            }

            swap(k, indices[i], indices[j]);
        }
    }

    printf("swap: %c and %c\n", k->layout[bestIndices[0]], k->layout[bestIndices[1]]);
    printPercentages(&bestKeyboard);
    return 0;
}
Exemplo n.º 8
0
//Runs the genetic algorithm
//Note: Longer than 24 lines due to extensive commenting needed
void Solver::runGenetic()
{
    //Uses top 20% of children
    int keep = gateLimit/5;
    for(int i=0;i<keep;++i)
    {
        circuits.push_back(Circuit());
    }
    addNewGates(keep);
    bool go = true;
    int loc = -1;
    unsigned long long int generation=0;
    do
    {
        ++generation;
        //Randomly deletes a gate every 100 generations
        if(generation%100==0)
        {
            randomDelete();
        }
        //Gets all crosses for top 20% of children every 20 generations
        if(generation%20==0)
        {
            crossover(keep);
        }
        //Mutates a Random Gate every 10 generations
        if(generation%10==0)
        {
            mutate();
        }
        //Adds a new random Gate every generation
        addNewGates(keep);
        calcFitness();
        runSortFitness();
        shrink();
        cull();
        loc = checkSolution();
        if(generation%1000 == 0)
        {
            cout<<"Generation: "<<generation<<"\n";
            cout<<"Num Gates:  "<<circuits[0].getGateNum()<<"\n";
        }
        if(loc != -1)
        {
            solutionLoc = loc;
            cout<<"Generation: "<<generation<<"\n";
            go = false;
        }
    }while(go);
}
Exemplo n.º 9
0
specimen_t population::populate(void)
{
	specimen_t indi;
	uint64_t iter;

	for (iter=0; iter<NUMBER_DIMENSIONS; iter++)
	{
		indi.cc.vel[iter] = rudi_.uniform((double)min_.vel[iter],(double)max_.vel[iter]);
		indi.cc.pos[iter] = rudi_.uniform((double)min_.pos[iter],(double)max_.pos[iter]);
	}

//	indi.gen = discretize(indi.cc);
	discretize(indi);
	fixer(indi);
	indi.fit = calcFitness(indi.gen);
	indi.calced = fitness_calculation_counter_;
	indi.bc = indi.cc;
	indi.bf = indi.fit;
	return indi;
}
Exemplo n.º 10
0
/*
 * Calculates fitness without score multipliers. Useful for producing 
 * human-readable output.
 */
int calcFitnessDirect(Keyboard *k)
{
	calcFitness(k); // Otherwise, k->fitness, k->fingerUsage, and k->fingerWork 
	                // would not get assigned properly.

	int i;
	k->inRoll     = 0;
	k->outRoll    = 0;
	k->sameHand   = 0;
	k->sameFinger = 0;
	k->rowChange  = 0;
	k->homeJump   = 0;
	k->ringJump   = 0;
	k->toCenter   = 0;
	k->toOutside  = 0;

	for (i = 0; i < diLen; ++i) scoreDigraphDirect(k, digraphs[i].key,
                                                   digraphs[i].value);

	return 0;
}
Exemplo n.º 11
0
int main() {
    srand(time(NULL));
    cfg_t cfg = {0};
    configureGA(&cfg);
    printf("Initial population: %d\nUniform rate: %f\nMutation rate: %f\nTarget genome: %s\n"
            , cfg.initialPopulation
            , cfg.uniformRate
            , cfg.mutationRate
            , cfg.targetGenome);

    population p = createPopulation(cfg.initialPopulation, true);
    for (uint8_t i = 0; i < cfg.initialPopulation; i++) {
        calcFitness(p[i], cfg.targetGenome);
        printf("%s (fit: %d)\n", p[i]->genes, p[i]->fitnessValue);
    }
    individual * ind = createIndividual(false);
    uint16_t counter = 0;
    evolve(p, &cfg, ind, counter);


    return 0;
}
Exemplo n.º 12
0
int Individual::getFitness () {
    calcFitness ();
    return this->fitness;
}
/**The main loop function that runs a step of the simulation
*stepsize: The size of the step in Bullet seconds
**/
void Physics::simulationLoopStep(float stepSize){
	totaltime += stepSize*1000;
	if(m_dynamicsWorld->getNumCollisionObjects()>1){
		if(theNet!=NULL){
			theNet->computeNetwork();
			for(int i=0;i< (int) subnets.size();i++){
				subnets.at(i)->computeNetwork();
			}
		}
		if(enableEffectors){
			for(int i=0;i< (int) effectorNNindex.size();i=i+3){
				#ifdef NNMAINONLY
				setEffect(i/3,
					theNet->getOutput(effectorNNindex.at(i)),
					theNet->getOutput(effectorNNindex.at(i+1)),
					theNet->getOutput(effectorNNindex.at(i+2))
					);
				#else
				setEffect(i/3,
					subnets.at(i/3)->getOutput(effectorNNindex.at(i)),
					subnets.at(i/3)->getOutput(effectorNNindex.at(i+1)),
					subnets.at(i/3)->getOutput(effectorNNindex.at(i+2))
					);

				#endif
			}
		}

		//fitness test
		calcFitness();
	}
	//fixed step... 1ms
	m_dynamicsWorld->stepSimulation(stepSize);

	for(int i=0; i < (int) sensors.size();i++){
		sensors.at(i)=0;
	}

	//collision detection
	//one per btPersistentManifold for each collision
	int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();

	for (int i=0;i<numManifolds;i++)
	{
		btPersistentManifold* contactManifold =  m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
		int box1 = (int)contactManifold->getBody0()->getUserPointer();
		int box2 = (int)contactManifold->getBody1()->getUserPointer();

		if(box1 >= 0){
			sensors.at(box1)=1;
		}
		if(box2 >= 0){
			sensors.at(box2)=1;
		}
	}

	//angel sensor
	for(int i = 0; i < m_dynamicsWorld->getNumConstraints(); i++){
		btGeneric6DofConstraint* constraint1;
		float x,y,z;

		//pointer == -1 if its not a sensor
		if(((int)(m_dynamicsWorld->getConstraint(i)->getUserConstraintPtr()))>=0)
			switch((m_dynamicsWorld->getConstraint(i))->getConstraintType()){
			case D6_CONSTRAINT_TYPE:
				constraint1 = (btGeneric6DofConstraint*) m_dynamicsWorld->getConstraint(i);

				x = constraint1->getRotationalLimitMotor(0)->m_currentPosition;
				y = constraint1->getRotationalLimitMotor(1)->m_currentPosition;
				z = constraint1->getRotationalLimitMotor(2)->m_currentPosition;

				sensors.at(((UserPointerStruct*)constraint1->getUserConstraintPtr())->sensorIndex)=x;
				sensors.at(((UserPointerStruct*)constraint1->getUserConstraintPtr())->sensorIndex+1)=y;
				sensors.at(((UserPointerStruct*)constraint1->getUserConstraintPtr())->sensorIndex+2)=z;

				break;
		}
	}
}
Exemplo n.º 14
0
int gameComputer(Keyboard *k, char difficulty)
{
	int bestp = -1;
	char bestc = '\0';
	int64_t score, bestScore = FITNESS_MAX;
	
	Keyboard k2;
	
	int indices[2 * trueksize];
	buildShuffledIndices(indices, 2 * trueksize);
	
	int i, j, inx, total = 0, done = FALSE;
	for (i = 0; i < monLen && !done; ++i) {
		if (locIgnoreShifted(k, monographs[i].key) != -1) continue;
		
		for (j = 0; j < ksize && !done; ++j) {
			inx = indices[j];
			if (k->layout[inx]) continue;
			
			copyKeyboard(&k2, k);
			k2.layout[inx] = monographs[i].key;
			
			calcFitness(&k2);
			score = k2.fitness - k->fitness;
			if (score < bestScore) {
				bestp = inx;
				bestc = monographs[i].key;
				bestScore = score;
			}
			
			++total;
			switch (difficulty) {
			case '0': 
				if (total >=  2) done = TRUE; break;
			case '1': 
				if (total >=  5) done = TRUE; break;
			case '2': 
				if (total >= 12) done = TRUE; break;
			case '3': 
				if (total >= 20) done = TRUE; break;
			case '4': 
				if (total >= 30) done = TRUE; break;
			case '5': 
				if (total >= 45) done = TRUE; break;
			case '6': 
				if (total >= 65) done = TRUE; break;
			case '7': 
				if (total >= 90) done = TRUE; break;
			case '8': 
				if (total >=130) done = TRUE; break;
			case '9':
				if (total >=200) done = TRUE; break;
			default: 
				break;
			}
		}
	}
	
	if (bestp >= 0 && bestc != '\0') {
		printf("The computer puts %c at %d.\n", bestc, bestp);
		k->layout[bestp] = bestc;
	}
	
	if (bestp < 0)
		fprintf(stderr, "Error: In gameComputer(), uninitialized value bestp.\n");
	if (bestc != '\0')
		fprintf(stderr, "Error: In gameComputer(), uninitialized value bestc.\n");		

	return 0;	
}
Exemplo n.º 15
0
void population::iterate(void)
{
	// Check for lack of improvement in best particle (over GENERATION_LIMIT iterations, then stop processing)
	if (fitness_calculation_counter_ > (best_in_swarm_.calced + (pop_size_ * GENERATION_LIMIT)) )
		return;

	uint64_t iter, jter;

	for (iter=0; iter<pop_size_; iter++)
	{
		for (jter=0; jter<NUMBER_DIMENSIONS; jter++)
		{
			// Update velocity
			pop_[iter].cc.vel[jter] =	(pop_[iter].cc.vel[jter] * inertia_)
				+ ( (rudi_.uniform((double)0.0,(double)1.0) * cog_) * (pop_[iter].bc.pos[jter]     - pop_[iter].cc.pos[jter]) )
				+ ( (rudi_.uniform((double)0.0,(double)1.0) * soc_) * (best_in_swarm_.cc.pos[jter] - pop_[iter].cc.pos[jter]) );

			if (pop_[iter].cc.vel[jter] > max_.vel[jter])
				pop_[iter].cc.vel[jter] = max_.vel[jter];
			else if (pop_[iter].cc.vel[jter] < min_.vel[jter])
				pop_[iter].cc.vel[jter] = min_.vel[jter];

			// Update position
			pop_[iter].cc.pos[jter] += pop_[iter].cc.vel[jter];

			if (pop_[iter].cc.pos[jter] > max_.pos[jter])
				pop_[iter].cc.pos[jter] = max_.pos[jter];
			else if (pop_[iter].cc.pos[jter] < min_.pos[jter])
				pop_[iter].cc.pos[jter] = min_.pos[jter];

/*
			// discretize
			if ( rudi_.uniform((double)0.0,(double)1.0) < (double)( 1.0/ (1.0+exp(pop_[iter].cc.vel[jter] * -1.0)) ) )
			{
				pop_[iter].cc.pos[jter] = 1.0;
				pop_[iter].gen[jter] = 1;
			}
			else
			{
				pop_[iter].cc.pos[jter] = 0.0;
				pop_[iter].gen[jter] = 0;
			}
*/
		}
		discretize(pop_[iter]);
		fixer(pop_[iter]);
//		pop_[iter].gen = discretize(pop_[iter].cc);
		pop_[iter].fit = calcFitness(pop_[iter].gen);
		pop_[iter].calced = fitness_calculation_counter_;

		if (pop_[iter].fit > pop_[iter].bf)
		{
			pop_[iter].bc = pop_[iter].cc;
			pop_[iter].bf = pop_[iter].fit;
		}
//		cout << "ID: " << iter << "\tGEN: " << pop_[iter].gen << endl;
	}

	generation_++;
	bestest();
}
Exemplo n.º 16
0
int gameComputer(Keyboard *k, char difficulty)
{
    int bestp;
    char bestc;
    int64_t score, bestScore = LLONG_MAX;

    Keyboard k2;

    shuffleIndices();

    int i, j, inx, total = 0, done = FALSE;
    for (i = 0; i < monLen && !done; ++i) {
        if (locWithoutShifted(k, monKeys[i]) != -1) continue;

        for (j = 0; j < ksize && !done; ++j) {
            inx = indices[j];
            if (k->layout[inx]) continue;

            copy(&k2, k);
            k2.layout[inx] = monKeys[i];

            calcFitness(&k2);
            score = k2.fitness - k->fitness;
            if (score < bestScore) {
                bestp = inx;
                bestc = monKeys[i];
                bestScore = score;
            }

            ++total;
            switch (difficulty) {
            case '0':
                if (total >=  2) done = TRUE;
                break;
            case '1':
                if (total >=  5) done = TRUE;
                break;
            case '2':
                if (total >= 12) done = TRUE;
                break;
            case '3':
                if (total >= 20) done = TRUE;
                break;
            case '4':
                if (total >= 30) done = TRUE;
                break;
            case '5':
                if (total >= 45) done = TRUE;
                break;
            case '6':
                if (total >= 65) done = TRUE;
                break;
            case '7':
                if (total >= 90) done = TRUE;
                break;
            case '8':
                if (total >=130) done = TRUE;
                break;
            case '9':
                if (total >=200) done = TRUE;
                break;
            default:
                break;
            }
        }
    }

    printf("The computer puts %c at %d.\n", bestc, bestp);
    k->layout[bestp] = bestc;
    return 0;
}
Exemplo n.º 17
0
int game()
{
    printf("\tWelcome to the keyboard layout game. The object of the game is ");
    printf("to get the lowest score possible. The way the game works is ");
    printf("that we start with a blank keyboard and players take turns placing ");
    printf("keys. Every time you increase the cost of the keyboard, your ");
    printf("score increases by the difference between the new keyboard cost ");
    printf("and the previous keyboard cost.\n");
    printf("\tAt each round you type in a character, a space, and the position ");
    printf("at which you want to place the character. For example if you wanted ");
    printf("to put the letter 'c' at position 5, you would type in \"c 5\".");
    printf("\n\n");

    int divisor = 10000;
    char input[1000];

    int p2_computer = TRUE;
    char difficulty = '\0';

    do {
        printf("Play against a human or the computer? (h/c) ");
        fgets(input, 999, stdin);
        if (input[0] == 'h') {
            p2_computer = FALSE;
            printf("Human it is.\n\n");
        } else {
            printf("Computer it is. Select a difficulty level (a number from 0 to 9): ");
            fgets(input, 999, stdin);
            difficulty = input[0];
            if (difficulty >= '0' && difficulty <= '4')
                printf("Difficulty set to %c. Good luck!\n\n", difficulty);
            else if (difficulty >= '5' && difficulty <= '7')
                printf("You're in for a challenge. Good luck!\n\n");
            else if (difficulty == '8')
                printf("I hope you know what you're getting yourself into. Good luck...\n\n");
            else if (difficulty == '9')
                printf("You must be crazy to take on that kind of difficulty level. Good luck!\n\n");
            else if (difficulty == 'x')
                printf("Secret impossible mode enabled. If you manage to beat this level, please tell me how you did it.\n\n");
            else {
                printf("That is not a valid input. Please try again.\n\n");
                continue;
            }
        }
    } while (FALSE);

    int p1 = 0, p2 = 1;
    int64_t score[2];
    score[0] = 0;
    score[1] = 0;

    Keyboard k;
    copy(&k, &nilKeyboard);

    calcFitness(&k);

    int prev_fitness = k.fitness;

    int keynum;
    for (keynum = 0; keynum < ksize; ++keynum) {
        printLayoutOnly(&k);

        if (p2_computer && keynum % 2 == p2) {
            gameComputer(&k, difficulty);
        } else {

            printf("Player %d, type in a character and a position: ", keynum % 2 + 1);
            fgets(input, 999, stdin);
            if (strlen(input) < 3) {
                printf("Invalid input. Please try again.\n");
                --keynum;
                continue;
            }
            char c = input[0];
            int pos = atoi(input + 2);

            if (k.layout[pos]) {
                printf("That position is occupied. Please try again.\n");
                --keynum;
                continue;
            } else if (locWithoutShifted(&k, c) != -1) {
                printf("That character has already been placed. Please try again.\n");
                --keynum;
                continue;
            } else k.layout[pos] = c;

        }

        calcFitness(&k);

        /* The value added to the player's score is the difference of the keyboard's current
         * fitness and its previous fitness.
         */
        score[keynum % 2] += (k.fitness - prev_fitness) / divisor;
        prev_fitness = k.fitness;

        printf("Player 1 score: %lld\n", score[p1]);
        printf("Player 2 score: %lld\n\n", score[p2]);
    }

    printf("Layout final fitness: %lld\n", k.fitness);
    printLayoutOnly(&k);
    printf("\n");

    if (score[p1] < score[p2]) {
        printf("Player 1 wins!\n");
    } else if (score[p1] > score[p2]) {
        printf("Player 2 wins!\n");
    } else {
        printf("It's a tie!\n");
    }

    printf("\n");

    return 0;
}