Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void doPrecalc() {
- int nSame;
- int nDiversity;
- int nDiversityWLR;
- int nNone;
- int nSkull;
- int nBorder;
- int score;
- for(Tile topTile: all_Tiles) {
- for(Tile leftTile: all_Tiles) {
- for(Tile rightTile: all_Tiles) {
- for(Tile bottomTile: all_Tiles) {
- for(Tile centerTile: all_Tiles) {
- nSame = 0;
- if(topTile == centerTile) {
- ++nSame;
- }
- if(leftTile == centerTile) {
- ++nSame;
- }
- if(rightTile == centerTile) {
- ++nSame;
- }
- if(bottomTile == centerTile) {
- ++nSame;
- }
- nDiversity = 0;
- if(topTile == leftTile && isColorTile(topTile)) {
- ++nDiversity;
- }
- if(topTile == rightTile && isColorTile(topTile)) {
- ++nDiversity;
- }
- if(topTile == bottomTile && isColorTile(topTile)) {
- ++nDiversity;
- }
- if(leftTile == rightTile && isColorTile(leftTile)) {
- ++nDiversity;
- }
- if(leftTile == bottomTile && isColorTile(leftTile)) {
- ++nDiversity;
- }
- if(rightTile == bottomTile && isColorTile(rightTile)) {
- ++nDiversity;
- }
- nDiversityWLR = 0;
- if(topTile == leftTile && isColorTile(topTile)) {
- ++nDiversityWLR;
- }
- if(topTile == rightTile && isColorTile(topTile)) {
- ++nDiversityWLR;
- }
- if(topTile == bottomTile && isColorTile(topTile)) {
- ++nDiversityWLR;
- }
- if(leftTile == bottomTile && isColorTile(leftTile)) {
- ++nDiversityWLR;
- }
- if(rightTile == bottomTile && isColorTile(rightTile)) {
- ++nDiversityWLR;
- }
- nNone = 0;
- if(topTile == Tile::None) {
- ++nNone;
- }
- if(leftTile == Tile::None) {
- ++nNone;
- }
- if(rightTile == Tile::None) {
- ++nNone;
- }
- if(bottomTile == Tile::None) {
- ++nNone;
- }
- nSkull = 0;
- if(topTile == Tile::Skull) {
- ++nSkull;
- }
- if(leftTile == Tile::Skull) {
- ++nSkull;
- }
- if(rightTile == Tile::Skull) {
- ++nSkull;
- }
- if(bottomTile == Tile::Skull) {
- ++nSkull;
- }
- nBorder = 0;
- if(topTile == Tile::Border) {
- ++nBorder;
- }
- if(leftTile == Tile::Border) {
- ++nBorder;
- }
- if(rightTile == Tile::Border) {
- ++nBorder;
- }
- if(bottomTile == Tile::Border) {
- ++nBorder;
- }
- if(centerTile == Tile::Skull) {
- score = -1;
- score -= (nSkull >= 3) ? 4*(nSkull-2) : 0;
- } else if (isColorTile(centerTile)) {
- score = -5;
- if(nSame ==0 ) {
- score -= 8*(nNone == 0);
- score += nNone;
- }
- if(nSame == 1) {
- //Une paire
- score += 10;
- score += 3*(nNone>0);
- score += 0*nDiversity;
- score += nDiversityWLR;
- } else if(nSame == 2) {
- //Un triple
- score += 30 + 3*(nNone>0);
- if(!(leftTile == centerTile && leftTile == rightTile) && !(topTile == centerTile && bottomTile == topTile)) {
- score += 5;
- score += 2*nDiversityWLR;
- }
- score += nDiversityWLR;
- }
- score += 8*(nNone>0);
- score += 12*((isColorTile(leftTile)&& rightTile == Tile::None) || (isColorTile(rightTile)&& leftTile == Tile::None));
- score += 4*nNone;
- score -= 6*nBorder;
- score += 1*nDiversity;
- } else if (centerTile == Tile::None) {
- score = 8*nDiversity;
- } else {
- score = 0;
- }
- _precalculatedScore[static_cast<int>(centerTile)][static_cast<int>(topTile)][static_cast<int>(leftTile)][static_cast<int>(rightTile)][static_cast<int>(bottomTile)] = score;
- }
- }
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////////
- void evaluateGenome(Genome & genome, FitnessType &fitness, bool verbose, int* fillScenario, int scenarioNumber) {
- myNodeEval.overTop = false;
- board->loadBoard();
- fitness.gameLost = false;
- fitness.turnGameLost = 0;
- fitness.droppedManySkulls = false;
- fitness.turnDroppedManySkulls = 0;
- fitness.discountedScore = 0;
- fitness.boardArrangementQuality = 0;
- for(int turn = 0; turn < genome.genomeSize; ++turn) {
- myNodeEval.rotation = (genome.genes[turn]) & 3;
- myNodeEval.centerX = (genome.genes[turn]) >> 2;
- myNodeEval.turn = turn;
- board->doNode(myNodeEval);
- if(scenarios[scenarioNumber][turn] > 0) {
- board->dropSkulls(myNodeEval.pId, scenarios[scenarioNumber][turn]);
- }
- if(fillScenario != nullptr) {
- fillScenario[turn] = myNodeEval.nSkullsDropped;
- }
- if(myNodeEval.overTop) {
- fitness.gameLost = true;
- fitness.turnGameLost = turn;
- break;
- } else {
- if((turn < 3 || turn == 17) && ratioScoreBoardArrangement != 0) {
- board->fullEvaluateBoard(myNodeEval);
- fitness.boardArrangementQuality += myNodeEval.positionalEstimation*discountFactorBQ[turn];
- }
- fitness.discountedScore += (myNodeEval.scoreThisTurn)*discountFactor[turn];
- if(4*myNodeEval.nSkullsDropped > 4*SKULLS_DROPPED_THRESHOLD+turn-1 && !fitness.droppedManySkulls) {
- fitness.droppedManySkulls = true;
- //fitness.turnDroppedManySkulls = turn;
- //fitness.turnDroppedManySkulls = 23*turn+2*turn*turn-20*std::min(12, myNodeEval.nSkullsDropped)+3*turn*std::min(12, myNodeEval.nSkullsDropped);
- fitness.turnDroppedManySkulls = 4*turn - std::min(12, myNodeEval.nSkullsDropped);
- }
- }
- if(verbose) {
- std::cerr << myNodeEval.centerX << " " <<myNodeEval.rotation << " " << board->nextTiles[2*turn] << " " << board->nextTiles[2*turn+1]<< " "<<myNodeEval.scoreThisTurn <<std::endl;
- board->dump(std::cerr);
- }
- }
- fitness.compoundedValue = fitness.discountedScore + ratioScoreBoardArrangement*(fitness.boardArrangementQuality);
- }
- /////////////////////////////////////////////////////////////////////////
- template <Behavior behavior> class TetrisFitness {
- public:
- bool gameLost;
- int turnGameLost;
- int discountedScore;
- int boardArrangementQuality;
- bool droppedManySkulls;
- int turnDroppedManySkulls=0;
- int compoundedValue;
- bool operator < (const TetrisFitness &other) const {
- if(behavior == Behavior::A) {
- // LOGD(discountedScore);
- // Maximize the score
- LEX_GT(gameLost);
- if(gameLost) {
- LEX_LT(turnGameLost); //If you lose, lose as late as possible
- }
- LEX_LT(droppedManySkulls);
- if(droppedManySkulls) {
- LEX_GT(turnDroppedManySkulls); //If you drop many skulls, do so ASAP
- }
- LEX_LT(compoundedValue);
- LEX_LT(discountedScore); //Maximize the score
- LEX_LT(boardArrangementQuality); //Maximize the arrangement quality
- return false;
- } else if (behavior == Behavior::B) {
- LOGD("Erreur");
- LEX_GT(gameLost);
- if(gameLost) {
- LEX_LT(turnGameLost); //If you lose, lose as late as possible
- }
- LEX_LT(droppedManySkulls);
- if(droppedManySkulls) {
- LEX_GT(turnDroppedManySkulls); //If you drop many skulls, do so ASAP
- }
- LEX_LT(discountedScore/1000+1000*boardArrangementQuality); //Maximize the score
- LEX_LT(boardArrangementQuality); //Maximize the arrangement quality
- return false;
- }
- else {
- LOGERR("Tetris fitness compare error");
- }
- }
- }
- ////////////////////////////////////////////////////////////
- void roundOutput(std::ostream& oStream) {
- std::string message = " M ";
- resetTimer();
- int timeUsed = 0;
- int popSize = 109;
- int genomeSize = 8;
- double discount = 0.80;
- int pId = 0;
- const Behavior behavior = Behavior::A;
- int BQImportance = 5+25.0*std::max(0.0,(40.0-board.nColor[0]-board.nSkull[0])/40.0);
- SKULLS_DROPPED_THRESHOLD = std::min(SKTH_ME_START,1+(6*12-board.nColor[0]-board.nSkull[0])/6) ;
- int oppPopSize = 71;
- int oppGenomeSize = 6;
- double oppDiscount = 0.85;
- int oppPId = 1;
- const Behavior oppBehavior = Behavior::A;
- int oppBQImportance = 0;
- if(environmentTurnNumber == 0) {
- saveGenome.init(genomeSize);
- saveOppGenome.init(oppGenomeSize);
- }
- //Initialize the genetic algorithm for me
- STCEvaluator<TetrisFitness<behavior>> evaluator(&board, popSize, genomeSize, discount, pId, BQImportance);
- GeneticAlgorithm <TetrisFitness<behavior>, STCEvaluator<TetrisFitness<behavior>>, GeneticEvolverBasic> tetrisGeneticAlgorithm(evaluator, popSize, genomeSize, 2, std::cout, false, true); //bool verbose, bool timeBased
- //Restore the best variation found last turn
- if(environmentTurnNumber > 0) {
- tetrisGeneticAlgorithm.population[0].genomes[1].init(genomeSize);
- tetrisGeneticAlgorithm.population[0].genomes[2].init(genomeSize);
- for(int i = 0; i < genomeSize-1; ++i) {
- tetrisGeneticAlgorithm.population[0].genomes[1].genes[i] = saveGenome.genes[i+1];
- tetrisGeneticAlgorithm.population[0].genomes[2].genes[i] = saveGenome.genes[i+1];
- }
- }
- if(environmentTurnNumber > 5 && board.nColor[0] > 7 && board.nColor[1] > 9) {
- //Initialize the opponent search
- STCEvaluator<TetrisFitness<oppBehavior>> opponentEvaluator(&board, oppPopSize, oppGenomeSize, oppDiscount, oppPId, oppBQImportance);
- GeneticAlgorithm <TetrisFitness<oppBehavior>, STCEvaluator<TetrisFitness<oppBehavior>>, GeneticEvolverBasic> opponentGA(opponentEvaluator, oppPopSize, oppGenomeSize, 2, std::cout, false, true); //bool verbose, bool timeBased
- //Restore the best variation found last turn
- if(environmentTurnNumber > 0) {
- opponentGA.population[0].genomes[1].init(oppGenomeSize);
- opponentGA.population[0].genomes[2].init(oppGenomeSize);
- for(int i = 0; i < oppGenomeSize-1; ++i) {
- opponentGA.population[0].genomes[1].genes[i] = saveOppGenome.genes[i+1];
- opponentGA.population[0].genomes[2].genes[i] = saveOppGenome.genes[i+1];
- }
- }
- //Find the best variation for me
- tetrisGeneticAlgorithm.setControls(MY_FIRST_TIME_LIMIT, 2*TIME_LIMIT);
- tetrisGeneticAlgorithm.doOptimize();
- timeUsed += MY_FIRST_TIME_LIMIT;
- Genome myBestGenome = tetrisGeneticAlgorithm.getBestGenome();
- TetrisFitness<behavior> fitnessThingMe;
- tetrisGeneticAlgorithm.entityEvaluator.evaluateGenome(myBestGenome, fitnessThingMe, false, opponentGA.entityEvaluator.scenarios[0], 0);
- LOGA("My variation : ");
- fitnessThingMe.toOutput(std::cerr);
- std::cerr << " ";
- for(int i = 0; i < MAX_HORIZON; ++i) {
- std::cerr<< opponentGA.entityEvaluator.scenarios[0][i]<<" ";
- }
- std::cerr<<std::endl;
- SKULLS_DROPPED_THRESHOLD = SKTH_OPP;
- //Find the best variation
- opponentGA.setControls(OPPGA_TIME_LIMIT, 2*OPPGA_TIME_LIMIT);
- timeUsed += OPPGA_TIME_LIMIT;
- opponentGA.doOptimize();
- //Save the best variation
- Genome bestGenome = opponentGA.getBestGenome();
- saveOppGenome = bestGenome;
- TetrisFitness<oppBehavior> fitnessThing;
- opponentGA.entityEvaluator.evaluateGenome(bestGenome, fitnessThing, false, tetrisGeneticAlgorithm.entityEvaluator.scenarios[0], 0);
- LOGA("His variation : ");
- fitnessThing.toOutput(std::cerr);
- std::cerr << " ";
- for(int i = 0; i < MAX_HORIZON; ++i) {
- std::cerr<< tetrisGeneticAlgorithm.entityEvaluator.scenarios[0][i]<<" ";
- }
- std::cerr<<std::endl;
- //Restore the best variation found last turn
- tetrisGeneticAlgorithm.popSwitch = 0;
- if(environmentTurnNumber > 0) {
- tetrisGeneticAlgorithm.population[0].genomes[1].init(genomeSize);
- tetrisGeneticAlgorithm.population[0].genomes[2].init(genomeSize);
- tetrisGeneticAlgorithm.population[0].genomes[3].init(genomeSize);
- tetrisGeneticAlgorithm.population[0].genomes[4].init(genomeSize);
- for(int i = 0; i < genomeSize-1; ++i) {
- tetrisGeneticAlgorithm.population[0].genomes[1].genes[i] = saveGenome.genes[i+1];
- tetrisGeneticAlgorithm.population[0].genomes[2].genes[i] = saveGenome.genes[i+1];
- }
- for(int i = 0; i < genomeSize; ++i) {
- tetrisGeneticAlgorithm.population[0].genomes[3].genes[i] = myBestGenome.genes[i];
- tetrisGeneticAlgorithm.population[0].genomes[4].genes[i] = myBestGenome.genes[i];
- }
- }
- for(int i = 5; i < popSize / 2 ; ++i) {
- tetrisGeneticAlgorithm.population[0].genomes[i].init(genomeSize);
- }
- int mySum = 0;
- int hisSum = 0;
- for(int i = 0; i < genomeSize; ++i) {
- mySum += opponentGA.entityEvaluator.scenarios[0][i];
- hisSum = tetrisGeneticAlgorithm.entityEvaluator.scenarios[0][i];
- if(hisSum > SEUIL_WIN && mySum < SEUIL_WIN - 1 && i > 0) {
- //He will drop a lot of stuff on me and I won't.
- //I need to drop something ASAP.
- tetrisGeneticAlgorithm.entityEvaluator.scenarios[0][i-1] = hisSum;
- std::cerr << "His new variation : ";
- for(int i = 0; i < MAX_HORIZON; ++i) {
- std::cerr<< tetrisGeneticAlgorithm.entityEvaluator.scenarios[0][i]<<" ";
- }
- std::cerr<<std::endl;
- message += "DEFENSE";
- break;
- }
- }
- }
- SKULLS_DROPPED_THRESHOLD = SKTH_ME_END;
- tetrisGeneticAlgorithm.setControls(TIME_LIMIT - getTimerDuration() + ((environmentTurnNumber == 0) ? 50000 : 0), 10*TIME_LIMIT);
- //Find the best variation
- tetrisGeneticAlgorithm.doOptimize();
- //Save the best variation
- Genome bestGenome2 = tetrisGeneticAlgorithm.getBestGenome();
- saveGenome = bestGenome2;
- TetrisFitness<behavior> bestFitness = tetrisGeneticAlgorithm.getBestFitness();
- //Print the principal variation
- LOGA("My Variation : ");
- bestFitness.toOutput(std::cerr);
- std::cerr << " ";
- TetrisFitness<behavior> fitnessThing2;
- tetrisGeneticAlgorithm.entityEvaluator.evaluateGenome(bestGenome2, fitnessThing2, false, tetrisGeneticAlgorithm.entityEvaluator.scenarios[1], 0);
- for(int i = 0; i < MAX_HORIZON; ++i) {
- std::cerr<< tetrisGeneticAlgorithm.entityEvaluator.scenarios[1][i]<<" ";
- }
- std::cerr<<std::endl;
- //Log the statistics
- LOGA("Round duration : "<< getTimerDuration());
- LOGA("Node count : "<< board.nodeCounter);
- LOGA("Generation count: " << tetrisGeneticAlgorithm.getGeneration());
- tetrisGeneticAlgorithm.entityEvaluator.evaluateGenome(bestGenome2, fitnessThing2, true, nullptr, 0);
- board.dump(std::cerr);
- board.loadBoard();
- board.dump(std::cerr);
- //Predict my future board state.
- Node myNode;
- myNode.pId = 0;
- myNode.nSkullsDropped = 0;
- myNode.rotation = (bestGenome2.genes[0]) & 3;
- myNode.centerX = (bestGenome2.genes[0]) >> 2;
- myNode.turn = 0;
- board.loadBoard();
- board.doNode(myNode);
- saveSkullsDropped = myNode.nSkullsDropped;
- //Output the move that should be played
- oStream << myNode.centerX << " " << myNode.rotation <<message <<std::endl;
- environmentTurnNumber++;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement