double MouseAgent::alphaBeta( const GameState& state, int level, double alpha, double beta, Action* actionPtr) const { if (state.gameOver() || level == (kAlphaBetaDepth * state.getNumAgents())) { return evaluate(state); } int agentIndex = level % state.getNumAgents(); bool isMax = (agentIndex == 0); double value = isMax ? -kInfinity : kInfinity; vector<Action> actions = isMax ? state.getActions(agentIndex) : vector<Action>(1, cats_[agentIndex - 1].getAction(state)); vector<Action> bestActions; for (size_t i = 0; i < actions.size(); i++) { const GameState successor = state.getNext(actions[i]); double nextV = alphaBeta(successor, level + 1, alpha, beta, actionPtr); if (isMax) { if (value < nextV) { if (level == 0) { bestActions.clear(); bestActions.push_back(actions[i]); } value = nextV; } else if ((value == nextV) && (level == 0)) { bestActions.push_back(actions[i]); } if (value >= beta) { break; } alpha = max(alpha, value); } else { if (value > nextV) { if (level == 0) { bestActions.clear(); bestActions.push_back(actions[i]); } value = nextV; } else if ((value == nextV) && (level == 0)) { bestActions.push_back(actions[i]); } if (value <= alpha) { break; } beta = min(beta, value); } } if (level == 0) { *actionPtr = bestActions.at(rand() % bestActions.size()); } return value; }
double MouseAgent::evaluate(const GameState& state) const { hash_map<Position, double, PositionHash> distances; Utils::shortestDistances(state.getMousePosition(), state, &distances); if (state.gameOver()) { return -100000; } if (state.wasCheesed()) { return 5000; } double distanceCatsInverse = 0; double freedomScoreCats = 0; double manhattanDistanceNearestCat = kLevelRows; for (int i = 1; i <= state.getNumAgents() - 1; i++) { const Position& catPosition = state.getCatPosition(i); const double distance = Utils::mapGetDefault(distances, catPosition, kInfinity); const double manhattanDistance = Utils::manhattanDistance(state.getMousePosition(), catPosition); if (distance > 1) { distanceCatsInverse += (1 / (distance - 1)); } else { // mouse cant get away return -100000; } if (!state.isCatStuck(i) && (manhattanDistance < manhattanDistanceNearestCat)) { manhattanDistanceNearestCat = manhattanDistance; } freedomScoreCats += Utils::freedomScore(catPosition, state, 6); } double distanceCheesesInverse = 0; double numCheese = 0; for (int y = 0; y < kLevelCols; y++) { for (int x = 0; x < kLevelCols; x++) { if (state.isCheesePosition(x, y)) { numCheese++; const double distance = Utils::mapGetDefault(distances, Position(x, y), kInfinity); if (distance >= 1) { distanceCheesesInverse += (1 / distance); } } } } double cheeseSquashed = state.numCheeseSquashed(); double score = state.getDecayedScore(); double blocksMoved = state.getNumBlocksMoved(); double value = -weights_.at(0) * distanceCatsInverse + -weights_.at(1) * manhattanDistanceNearestCat + -weights_.at(2) * freedomScoreCats + weights_.at(3) * distanceCheesesInverse + weights_.at(4) * score + weights_.at(5) * blocksMoved + -weights_.at(6) * cheeseSquashed; return value; }
void ObjectBank::applyCollision(GameState& gstate) { bool playerKilled = false; unsigned int barriersKilled = 0; unsigned int enemiesKilled = 0; unsigned int collectedBonusCounter = 0; sf::Color rainbowColor = Palette::fromHSV(gstate.getRainbowGradient(),1,1); Pool<Barrier>::iterator itBarrier = m_barriersPool.begin(); for ( ; itBarrier != m_barriersPool.end() ; ++itBarrier) { BarrierCollisionResult bcr = Collider::collides(m_player,*itBarrier); if ( bcr.collided ) { switch (bcr.getLoser()) { case BarrierCollisionResult::BARRIER: createBonus(itBarrier->getLeftEdgePosition()); createBonus(itBarrier->getRightEdgePosition()); createExplosion(itBarrier->getPosition()); itBarrier->kill(); barriersKilled+=2; gstate.getBorders().impulse(rainbowColor); break; case BarrierCollisionResult::PLAYER: playerKilled = true; break; } break; } } Pool<RadialExplosion>::const_iterator itExplosion = m_explosionsPool.begin(); for ( ; itExplosion != m_explosionsPool.end() ; ++itExplosion ) { auto enemies = gstate.getEnemyGrid().getNeighbours(Sphere(itExplosion->getCenter(),itExplosion->getRadius())); for (Enemy* enemy : enemies) { enemy->kill(); createEnemyDeath(enemy->getPosition()); createBonus(enemy->getPosition()); createParticleSystem(enemy->getPosition(),rainbowColor); enemiesKilled +=1; } } auto enemies = gstate.getEnemyGrid().getNeighbours(m_player.getPosition()); for (Enemy* enemy : enemies) { CollisionResult cr = Collider::collides(m_player,*enemy); if ( cr.collided ) { playerKilled = true; } } Pool<Bonus>::iterator itBonusses = m_bonusPool.begin(); for ( ; itBonusses != m_bonusPool.end() ; ++itBonusses ) { CollisionResult cr = Collider::collides(m_player,*itBonusses); if ( cr.collided ) { itBonusses->kill(); collectedBonusCounter++; } } // Purge all collided elements m_barriersPool.purge(std::bind(&Entity::isDead, std::placeholders::_1)); m_enemiesPool.purge(std::bind(&Entity::isDead, std::placeholders::_1)); m_bonusPool.purge(std::bind(&Bonus::isDead, std::placeholders::_1)); gstate.getScore().addMultiplier(collectedBonusCounter); gstate.getScore().addKill(enemiesKilled,barriersKilled); if (playerKilled) { gstate.gameOver(); gstate.reset(); } }