OpentableDataset::ObjectId OpentableDataset::FindMatchingObjectIdImpl(FeatureBuilder1 const & fb) const { auto const name = fb.GetName(StringUtf8Multilang::kDefaultCode); if (name.empty()) return Object::InvalidObjectId(); // Find |kMaxSelectedElements| nearest values to a point. auto const nearbyIds = GetNearestObjects(MercatorBounds::ToLatLon(fb.GetKeyPoint()), kMaxSelectedElements, kDistanceLimitInMeters); for (auto const objId : nearbyIds) { if (sponsored_scoring::Match(GetObjectById(objId), fb).IsMatched()) return objId; } return Object::InvalidObjectId(); }
void CPlayerAI::Think(COutputControl * playerKeys) { short iDecisionPercentage[5] = {25, 35, 50, 75, 100}; //Clear out the old input settings playerKeys->game_left.fDown = false; playerKeys->game_right.fDown = false; //A percentage of the time the cpu will do nothing based on the difficulty level if (RandomNumberGenerator::generator().getBoolean(100, iDecisionPercentage[game_values.cpudifficulty]) && pPlayer->isready()) return; playerKeys->game_jump.fDown = false; playerKeys->game_down.fDown = false; playerKeys->game_turbo.fDown = false; playerKeys->game_powerup.fDown = false; if (pPlayer->isdead() || pPlayer->isspawning()) return; /*************************************************** * 1. Figure out what objects are nearest to us ***************************************************/ GetNearestObjects(); short iTenSeconds = 15 * iDecisionPercentage[game_values.cpudifficulty] / 10; //If there is a goal, then make sure we aren't paying attention to it for too long if (nearestObjects.goal) { if (currentAttentionObject.iID == nearestObjects.goal->iNetworkID) { //If we have been paying attention to this goal for too long, then start ignoring it if (++currentAttentionObject.iTimer > iTenSeconds) { AttentionObject * ao = new AttentionObject(); ao->iID = currentAttentionObject.iID; ao->iType = 1; //Ignore this object ao->iTimer = iTenSeconds; attentionObjects[ao->iID] = ao; } } else { currentAttentionObject.iID = nearestObjects.goal->iNetworkID; currentAttentionObject.iTimer = 0; } } else { currentAttentionObject.iID = -1; } //Expire attention objects std::vector<int> toDelete; std::map<int, AttentionObject*>::iterator itr = attentionObjects.begin(), lim = attentionObjects.end(); while (itr != lim) { if (itr->second->iTimer > 0) { if (--(itr->second->iTimer) == 0) { toDelete.push_back(itr->first); } } ++itr; } for (std::vector<int>::iterator tdIt = toDelete.begin(); tdIt != toDelete.end(); ++tdIt) { // perform the actual disposal and removal std::map<int, AttentionObject*>::iterator deadObjIt = attentionObjects.find(*tdIt); delete deadObjIt->second; attentionObjects.erase(deadObjIt); } short iStoredPowerup = game_values.gamepowerups[pPlayer->globalID]; MO_CarriedObject * carriedItem = pPlayer->carriedItem; short ix = pPlayer->ix; short iy = pPlayer->iy; short iTeamID = pPlayer->teamID; /*************************************************** * 2. Figure out priority of actions ***************************************************/ short actionType = 0; if (nearestObjects.threat && nearestObjects.threatdistance < 14400) { actionType = 2; } else if (nearestObjects.stomp && nearestObjects.stompdistance < 14400) { actionType = 4; } else if (nearestObjects.goal && nearestObjects.teammate) { if (nearestObjects.goaldistance < nearestObjects.teammatedistance) actionType = 1; else actionType = 3; } else if (nearestObjects.teammate) { actionType = 3; } else if (nearestObjects.goal) { if (nearestObjects.playerdistance < 4096) actionType = 0; else actionType = 1; } else { actionType = 0; } /*************************************************** * 3. Deal with closest item ***************************************************/ //return if no players, goals, or threats available if (((actionType != 0) || nearestObjects.player) && (actionType != 1 || nearestObjects.goal) && ((actionType != 2) || nearestObjects.threat) && ((actionType != 3) || nearestObjects.teammate) && ((actionType != 4) || nearestObjects.stomp) && (iFallDanger == 0)) { //Use turbo if (pPlayer->bobomb) { if (nearestObjects.playerdistance <= 4096 || nearestObjects.stompdistance <= 4096 || nearestObjects.threatdistance <= 4096) playerKeys->game_turbo.fDown = true; } else { if (pPlayer->powerup == -1 || !RandomNumberGenerator::generator().getBoolean(20)) playerKeys->game_turbo.fDown = true; if (carriedItem) { //Hold important mode goal objects (we'll drop the star later if it is a bad star) MovingObjectType carriedobjecttype = carriedItem->getMovingObjectType(); if ((carriedobjecttype == movingobject_egg) || (carriedobjecttype == movingobject_flag) || (carriedobjecttype == movingobject_star) || (carriedobjecttype == movingobject_phantokey)) { playerKeys->game_turbo.fDown = true; } } } if (actionType == 0) { //Kill nearest player CPlayer * player = nearestObjects.player; bool * moveToward; bool * moveAway; if ((player->ix > ix && nearestObjects.playerwrap) || (player->ix < ix && !nearestObjects.playerwrap)) { moveToward = &playerKeys->game_left.fDown; moveAway = &playerKeys->game_right.fDown; } else { moveToward = &playerKeys->game_right.fDown; moveAway = &playerKeys->game_left.fDown; } //Move player relative to opponent when we are playing star mode and we are holding a star if (game_values.gamemode->gamemode == game_mode_star) { if (carriedItem && carriedItem->getMovingObjectType() == movingobject_star) { if (((CO_Star*)carriedItem)->getType() == 1) *moveAway = true; else { *moveToward = true; //If player is close if (player->iy <= iy && player->iy > iy - 60 && player->ix - ix < 90 && player->ix - ix > -90) { //And we are facing toward that player, throw the star if ((player->ix > ix && pPlayer->IsPlayerFacingRight()) || ((player->ix < ix) && !pPlayer->IsPlayerFacingRight())) { pPlayer->throw_star = 30; playerKeys->game_turbo.fDown = false; } } } } } //Move player relative to opponent when we are carrying a weapon like a shell or throwblock else if (carriedItem) { if (carriedItem->getMovingObjectType() == movingobject_shell || carriedItem->getMovingObjectType() == movingobject_throwblock) { *moveToward = true; //If player is close if (player->iy > iy - 10 && player->iy < iy + 30 && abs(player->ix - ix) < 150) { //And we are facing toward that player, throw the projectile if ((player->ix > ix && pPlayer->IsPlayerFacingRight()) || ((player->ix < ix) && !pPlayer->IsPlayerFacingRight())) { playerKeys->game_turbo.fDown = false; } } } } else if (game_values.gamemode->tagged == player || player->invincible || player->shyguy || game_values.gamemode->chicken == pPlayer) { *moveAway = true; } else if (pPlayer->invincible || pPlayer->shyguy || pPlayer->bobomb || game_values.gamemode->tagged == pPlayer) { *moveToward = true; } else if (player->iy >= iy && !player->invincible && !player->bobomb) { *moveToward = true; } else { if (nearestObjects.playerdistance < 8100) //else if player is near but higher, run away (left) *moveAway = true; } if (player->iy <= iy && //jump if player is higher or at the same level and player->ix - ix < 45 && //player is very near player->ix - ix > -45) { //or if player is high playerKeys->game_jump.fDown = true; } else if (player->iy > iy && //try to down jump if player is below us player->ix - ix < 45 && player->ix - ix > -45 && RandomNumberGenerator::generator().getBoolean()) { //or if player is high playerKeys->game_jump.fDown = true; playerKeys->game_down.fDown = true; if (!pPlayer->superstomp_lock) { //If the player is tanooki, then try to super stomp on them if (pPlayer->tanooki) { playerKeys->game_turbo.fPressed = true; pPlayer->lockfire = false; } else if (pPlayer->iKuriboShoe > 0) { //else if the player has the shoe then stomp playerKeys->game_down.fPressed = true; playerKeys->game_jump.fPressed = true; } } } else if (iy - player->iy > 70) { //If the player is significatly below us, then jump playerKeys->game_jump.fDown = true; } else { if (!RandomNumberGenerator::generator().getBoolean(60)) playerKeys->game_jump.fDown = true; } } else if (actionType == 1) { //Go for goal CObject * goal = nearestObjects.goal; if ((goal->ix > ix && nearestObjects.goalwrap) || (goal->ix < ix && !nearestObjects.goalwrap)) playerKeys->game_left.fDown = true; else playerKeys->game_right.fDown = true; if (goal->iy <= iy && goal->ix - ix < 45 && goal->ix - ix > -45) { playerKeys->game_jump.fDown = true; } else if (goal->iy > iy && goal->ix - ix < 45 && goal->ix - ix > -45) { playerKeys->game_jump.fDown = true; playerKeys->game_down.fDown = true; } else if (iy - goal->iy > 70) { playerKeys->game_jump.fDown = true; } else { if (!RandomNumberGenerator::generator().getBoolean(60)) playerKeys->game_jump.fDown = true; } if (goal->getObjectType() == object_moving && ((IO_MovingObject*)goal)->getMovingObjectType() == movingobject_egg) playerKeys->game_turbo.fDown = true; else if (goal->getObjectType() == object_moving && ((IO_MovingObject*) goal)->getMovingObjectType() == movingobject_star && pPlayer->throw_star == 0) playerKeys->game_turbo.fDown = true; else if (goal->getObjectType() == object_moving && ((IO_MovingObject*) goal)->getMovingObjectType() == movingobject_flag) playerKeys->game_turbo.fDown = true; //Drop current item if we're going after another carried item if (carriedItem) { if (goal->getObjectType() == object_moving) { MovingObjectType goalobjecttype = ((IO_MovingObject*)goal)->getMovingObjectType(); if (goalobjecttype == movingobject_egg || goalobjecttype == movingobject_flag || goalobjecttype == movingobject_star || goalobjecttype == movingobject_phantokey) { MovingObjectType carriedobjecttype = carriedItem->getMovingObjectType(); //If we are holding something that isn't a mode goal object, then drop it if (carriedobjecttype != movingobject_egg && carriedobjecttype != movingobject_flag && carriedobjecttype != movingobject_star && carriedobjecttype != movingobject_phantokey) { playerKeys->game_turbo.fDown = false; } } } } //Open treasure chests in bonus houses in world mode if (goal->getObjectType() == object_moving && ((IO_MovingObject*)goal)->getMovingObjectType() == movingobject_treasurechest) playerKeys->game_turbo.fPressed = true; } else if (actionType == 2) { //Evade Threat CObject * threat = nearestObjects.threat; //If threat, always use turbo playerKeys->game_turbo.fDown = true; if ((threat->ix > ix && nearestObjects.threatwrap) || (threat->ix < ix && !nearestObjects.threatwrap)) playerKeys->game_right.fDown = true; else playerKeys->game_left.fDown = true; if (threat->iy <= iy && threat->ix - ix < 60 && threat->ix - ix > -60) { playerKeys->game_jump.fDown = true; playerKeys->game_down.fDown = true; } else if (threat->iy > iy && threat->ix - ix < 60 && threat->ix - ix > -60) { playerKeys->game_jump.fDown = true; } } else if (actionType == 3) { //Tag teammate CPlayer * teammate = nearestObjects.teammate; if ((teammate->ix > ix && nearestObjects.teammatewrap) || (teammate->ix < ix && !nearestObjects.teammatewrap)) playerKeys->game_left.fDown = true; else playerKeys->game_right.fDown = true; if (teammate->iy <= iy && teammate->ix - ix < 45 && teammate->ix - ix > -45) { playerKeys->game_jump.fDown = true; } else if (teammate->iy > iy && teammate->ix - ix < 45 && teammate->ix - ix > -45) { playerKeys->game_jump.fDown = true; playerKeys->game_down.fDown = true; } else if (iy - teammate->iy > 70) { playerKeys->game_jump.fDown = true; } else { if (!RandomNumberGenerator::generator().getBoolean(60)) playerKeys->game_jump.fDown = true; } } else if (actionType == 4) { //Stomp something (goomba, koopa, cheepcheep) CObject * stomp = nearestObjects.stomp; bool * moveToward; bool * moveAway; if ((stomp->ix > ix && nearestObjects.stompwrap) || (stomp->ix < ix && !nearestObjects.stompwrap)) { moveToward = &playerKeys->game_left.fDown; moveAway = &playerKeys->game_right.fDown; } else { moveToward = &playerKeys->game_right.fDown; moveAway = &playerKeys->game_left.fDown; } if (stomp->iy > iy + PH || pPlayer->shyguy || pPlayer->invincible || (carriedItem && (carriedItem->getMovingObjectType() == movingobject_shell || carriedItem->getMovingObjectType() == movingobject_throwblock))) { //if true stomp target is lower or at the same level, run toward *moveToward = true; } else { if (nearestObjects.stompdistance < 8100) *moveAway = true; else *moveToward = true; } if (stomp->iy <= iy + PH && nearestObjects.stompdistance < 2025) { playerKeys->game_jump.fDown = true; } else if (stomp->iy > iy + PH && nearestObjects.stompdistance < 2025) { playerKeys->game_jump.fDown = true; playerKeys->game_down.fDown = true; if (!pPlayer->superstomp_lock) { //If the player is tanooki, then try to super stomp on them if (pPlayer->tanooki) { playerKeys->game_turbo.fPressed = true; pPlayer->lockfire = false; } else if (pPlayer->iKuriboShoe > 0) { //else if the player has the shoe then stomp playerKeys->game_down.fPressed = true; playerKeys->game_jump.fPressed = true; } } } else { if (!RandomNumberGenerator::generator().getBoolean(60)) playerKeys->game_jump.fDown = true; } } } //"Star Mode" specific stuff //Drop the star if we're not it if (game_values.gamemode->gamemode == game_mode_star) { CGM_Star * starmode = (CGM_Star*)game_values.gamemode; if (carriedItem && carriedItem->getMovingObjectType() == movingobject_star && ((CO_Star*)carriedItem)->getType() == 0 && !starmode->isplayerstar(pPlayer)) playerKeys->game_turbo.fDown = false; else if (starmode->isplayerstar(pPlayer) && pPlayer->throw_star == 0) playerKeys->game_turbo.fDown = true; } if (carriedItem) { MovingObjectType carriedobjecttype = carriedItem->getMovingObjectType(); //"Phanto Mode" specific stuff if (game_values.gamemode->gamemode == game_mode_chase) { //Ignore the key if a phanto is really close if (nearestObjects.threat && nearestObjects.threat->getObjectType() == object_phanto && nearestObjects.threatdistance < 4096) { playerKeys->game_turbo.fDown = false; //Ignore the key for a little while if (attentionObjects.find(carriedItem->iNetworkID) != attentionObjects.end()) { AttentionObject * ao = attentionObjects[carriedItem->iNetworkID]; ao->iType = 1; ao->iTimer = iDecisionPercentage[game_values.cpudifficulty] / 3; } else { AttentionObject * ao = new AttentionObject(); ao->iID = carriedItem->iNetworkID; ao->iType = 1; ao->iTimer = iDecisionPercentage[game_values.cpudifficulty] / 3; attentionObjects[ao->iID] = ao; } } } //If we are holding something that we are ignoring, drop it else if (attentionObjects.find(carriedItem->iNetworkID) != attentionObjects.end()) { playerKeys->game_turbo.fDown = false; } //Drop live bombs if they are not yours if (carriedobjecttype == movingobject_bomb) { CO_Bomb * bomb = (CO_Bomb*)carriedItem; if (bomb->iTeamID != pPlayer->teamID) playerKeys->game_turbo.fDown = false; } else if (carriedobjecttype == movingobject_carried || carriedobjecttype == movingobject_throwbox) { //Drop springs,spikes,shoes playerKeys->game_turbo.fDown = false; } } //Let go of the jump button so that we clear "lockjump" so we can jump again when we hit the ground if we want to if (pPlayer->inair && pPlayer->vely > 0 && (pPlayer->powerup != 3 || (pPlayer->powerup == 3 && pPlayer->lockjump))) playerKeys->game_jump.fDown = false; /*************************************************** * 4. Deal with falling onto spikes (this needs to be improved) ***************************************************/ //Make sure we don't jump over something that could kill us short iDeathY = iy / TILESIZE; short iDeathX1 = ix / TILESIZE; short iDeathX2; if (ix + PW >= smw->ScreenWidth) iDeathX2 = (ix + PW - smw->ScreenWidth) / TILESIZE; else iDeathX2 = (ix + PW) / TILESIZE; if (iDeathY < 0) iDeathY = 0; //short depth = -1; while (iDeathY < MAPHEIGHT) { int ttLeftTile = g_map->map(iDeathX1, iDeathY); int ttRightTile = g_map->map(iDeathX2, iDeathY); bool fDeathTileUnderPlayer1 = ((ttLeftTile & tile_flag_death_on_top) && (ttRightTile & tile_flag_death_on_top)) || ((ttLeftTile & tile_flag_death_on_top) && !(ttRightTile & tile_flag_solid)) || (!(ttLeftTile & tile_flag_solid) && (ttRightTile & tile_flag_death_on_top)); if (fDeathTileUnderPlayer1) { if (iFallDanger == 0) iFallDanger = (playerKeys->game_right.fDown ? -1 : 1); goto ExitDeathCheck; } else if ((ttLeftTile & tile_flag_solid) || (ttLeftTile & tile_flag_solid_on_top) || g_map->block(iDeathX1, iDeathY) || ((ttRightTile & tile_flag_solid) && (ttRightTile & tile_flag_solid_on_top)) || g_map->block(iDeathX2, iDeathY)) { iFallDanger = 0; goto ExitDeathCheck; } //Look through all platforms and see if we are hitting solid or death tiles in them for (short iPlatform = 0; iPlatform < g_map->iNumPlatforms; iPlatform++) { int lefttile = g_map->platforms[iPlatform]->GetTileTypeFromCoord(ix, iDeathY << 5); int righttile = g_map->platforms[iPlatform]->GetTileTypeFromCoord(ix + PW, iDeathY << 5); bool fDeathTileUnderPlayer2 = ((lefttile & tile_flag_death_on_top) && (righttile & tile_flag_death_on_top)) || ((lefttile & tile_flag_death_on_top) && !(righttile & tile_flag_solid)) || (!(lefttile & tile_flag_solid) && (righttile & tile_flag_death_on_top)); if (fDeathTileUnderPlayer2) { if (iFallDanger == 0) iFallDanger = (playerKeys->game_right.fDown ? -1 : 1); goto ExitDeathCheck; } else if ((lefttile & tile_flag_solid) || (lefttile & tile_flag_solid_on_top) || ((righttile & tile_flag_solid) && (righttile & tile_flag_solid_on_top))) { iFallDanger = 0; goto ExitDeathCheck; } } iDeathY++; } //If we are done checking for death under the player, come here ExitDeathCheck: //There is a death tile below us so move to the side that is safest if (iFallDanger < 0) { playerKeys->game_right.fDown = true; playerKeys->game_left.fDown = false; playerKeys->game_jump.fDown = true; playerKeys->game_turbo.fDown = true; playerKeys->game_down.fDown = false; } else if (iFallDanger > 0) { playerKeys->game_right.fDown = false; playerKeys->game_left.fDown = true; playerKeys->game_jump.fDown = true; playerKeys->game_turbo.fDown = true; playerKeys->game_down.fDown = false; } //Make sure we don't jump up into something that can kill us iDeathY = iy / TILESIZE; if (iDeathY < 0) iDeathY = 0; short heightlimit = 3; while (iDeathY >= 0 && heightlimit > 0) { int ttLeftTile = g_map->map(iDeathX1, iDeathY); int ttRightTile = g_map->map(iDeathX2, iDeathY); if ((ttLeftTile & tile_flag_solid && (ttLeftTile & tile_flag_death_on_bottom) == 0) || (ttRightTile & tile_flag_solid && (ttRightTile & tile_flag_death_on_bottom) == 0) || g_map->block(iDeathX1, iDeathY) || g_map->block(iDeathX2, iDeathY)) { break; } else if (ttLeftTile & tile_flag_death_on_bottom || ttRightTile & tile_flag_death_on_bottom) { playerKeys->game_jump.fDown = false; break; } iDeathY--; heightlimit--; } /*************************************************** * 5. Use stored powerups ***************************************************/ if (iStoredPowerup > 0) { //use 1-5up, clock, pow, bulletbill, mod, podobo, right away if (iStoredPowerup == 1 || iStoredPowerup == 2 || iStoredPowerup == 3 || iStoredPowerup == 4 || iStoredPowerup == 7 || iStoredPowerup == 9 || iStoredPowerup == 10 || iStoredPowerup == 16 || iStoredPowerup == 22) { playerKeys->game_powerup.fDown = true; } else if (((iStoredPowerup == 5 || iStoredPowerup == 11 || iStoredPowerup == 17 || iStoredPowerup == 19 || iStoredPowerup == 21 || iStoredPowerup == 23 || iStoredPowerup == 24 || iStoredPowerup == 25) && pPlayer->powerup == -1) || //Use fireflower, hammer, feather, boomerang, cape, wings, sledge, bombs (iStoredPowerup == 6 && !pPlayer->invincible) || //Use star (iStoredPowerup == 8 && !pPlayer->bobomb) || //use bob-omb (iStoredPowerup >= 12 && iStoredPowerup <= 15 && !carriedItem) || //Use shell (iStoredPowerup == 20 && !pPlayer->tanooki)) { //use tanooki playerKeys->game_powerup.fDown = true; } else if (iStoredPowerup == 18) { //mystery mushroom //See if another player has a powerup for (short iPlayer = 0; iPlayer < list_players_cnt; iPlayer++) { if (iPlayer == pPlayer->localID || list_players[iPlayer]->teamID == iTeamID) continue; if (game_values.gamepowerups[list_players[iPlayer]->globalID] > 0) { playerKeys->game_powerup.fDown = true; break; } } } else if (iStoredPowerup == 26) { //jail key if (pPlayer->jailtimer > 0) playerKeys->game_powerup.fDown = true; } } }