bool CRewardableObject::wasVisited(const CGHeroInstance * h) const { switch (visitMode) { case VISIT_UNLIMITED: return false; case VISIT_BONUS: return h->hasBonusFrom(Bonus::OBJECT, ID); case VISIT_HERO: return h->visitedObjects.count(ObjectInstanceID(id)); default: return wasVisited(h->tempOwner); } }
int CAI_TacticalServices::FindLosNode(const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinThreatDist, float flMaxThreatDist, float flBlockTime, FlankType_t eFlankType, const Vector &vecFlankRefPos, float flFlankParam ) { if ( !CAI_NetworkManager::NetworksLoaded() ) return NO_NODE; AI_PROFILE_SCOPE( CAI_TacticalServices_FindLosNode ); MARK_TASK_EXPENSIVE(); int iMyNode = GetPathfinder()->NearestNodeToNPC(); if ( iMyNode == NO_NODE ) { Vector pos = GetOuter()->GetAbsOrigin(); DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); return NO_NODE; } // ------------------------------------------------------------------------------------ // We're going to search for a shoot node by expanding to our current node's neighbors // and then their neighbors, until a shooting position is found, or all nodes are beyond MaxDist // ------------------------------------------------------------------------------------ AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); CNodeList list( pBuffer, GetNetwork()->NumNodes() ); CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited // mark start as visited wasVisited.Set( iMyNode ); list.Insert( AI_NearNode_t(iMyNode, 0) ); static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; while ( list.Count() ) { int nodeIndex = list.ElementAtHead().nodeIndex; // remove this item from the list list.RemoveAtHead(); const Vector &nodeOrigin = GetNetwork()->GetNode(nodeIndex)->GetPosition(GetHullType()); // HACKHACK: Can't we rework this loop and get rid of this? // skip the starting node, or we probably wouldn't have called this function. if ( nodeIndex != iMyNode ) { bool skip = false; // See if the node satisfies the flanking criteria. switch ( eFlankType ) { case FLANKTYPE_NONE: break; case FLANKTYPE_RADIUS: { Vector vecDist = nodeOrigin - vecFlankRefPos; if ( vecDist.Length() < flFlankParam ) { skip = true; } break; } case FLANKTYPE_ARC: { Vector vecEnemyToRef = vecFlankRefPos - vThreatPos; VectorNormalize( vecEnemyToRef ); Vector vecEnemyToNode = nodeOrigin - vThreatPos; VectorNormalize( vecEnemyToNode ); float flDot = DotProduct( vecEnemyToRef, vecEnemyToNode ); if ( RAD2DEG( acos( flDot ) ) < flFlankParam ) { skip = true; } break; } } // Don't accept climb nodes, and assume my nearest node isn't valid because // we decided to make this check in the first place. Keep moving if ( !skip && !GetNetwork()->GetNode(nodeIndex)->IsLocked() && GetNetwork()->GetNode(nodeIndex)->GetType() != NODE_CLIMB ) { // Now check its distance and only accept if in range float flThreatDist = ( nodeOrigin - vThreatPos ).Length(); if ( flThreatDist < flMaxThreatDist && flThreatDist > flMinThreatDist ) { CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); if ( GetOuter()->IsValidShootPosition( nodeOrigin, pNode, pNode->GetHint() ) ) { if (GetOuter()->TestShootPosition(nodeOrigin,vThreatEyePos)) { // Note when this node was used, so we don't try // to use it again right away. GetNetwork()->GetNode(nodeIndex)->Lock( flBlockTime ); #if 0 if ( GetOuter()->GetHintNode() ) { GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); GetOuter()->SetHintNode( NULL ); } // This used to not be set, why? (kenb) // @Note (toml 05-19-04): I think because stomping the hint can lead to // unintended side effects. The hint node is primarily a high level // tool, and certain NPCs break if it gets slammed here. If we need // this, we should propagate it out and let the schedule selector // or task decide to set the hint node GetOuter()->SetHintNode( GetNetwork()->GetNode(nodeIndex)->GetHint() ); #endif if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:los!", nodeIndex), false, 1 ); } // The next NPC who searches should use a slight different pattern nSearchRandomizer = nodeIndex; return nodeIndex; } else { if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!shoot", nodeIndex), false, 1 ); } } } else { if ( ShouldDebugLos( nodeIndex ) ) { NDebugOverlay::Text( nodeOrigin, CFmtStr( "%d:!valid", nodeIndex), false, 1 ); } } } else { if ( ShouldDebugLos( nodeIndex ) ) { CFmtStr msg( "%d:%s", nodeIndex, ( flThreatDist < flMaxThreatDist ) ? "too close" : "too far" ); NDebugOverlay::Text( nodeOrigin, msg, false, 1 ); } } } } // Go through each link and add connected nodes to the list for (int link=0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks();link++) { int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) continue; int newID = nodeLink->DestNodeID(nodeIndex); // If not already visited, add to the list if (!wasVisited.IsBitSet(newID)) { float dist = (GetLocalOrigin() - GetNetwork()->GetNode(newID)->GetPosition(GetHullType())).LengthSqr(); list.Insert( AI_NearNode_t(newID, dist) ); wasVisited.Set( newID ); } } } // We failed. No range attack node node was found return NO_NODE; }
int CAI_TacticalServices::FindCoverNode(const Vector &vNearPos, const Vector &vThreatPos, const Vector &vThreatEyePos, float flMinDist, float flMaxDist ) { if ( !CAI_NetworkManager::NetworksLoaded() ) return NO_NODE; AI_PROFILE_SCOPE( CAI_TacticalServices_FindCoverNode ); MARK_TASK_EXPENSIVE(); DebugFindCover( NO_NODE, GetOuter()->EyePosition(), vThreatEyePos, 0, 255, 255 ); int iMyNode = GetPathfinder()->NearestNodeToPoint( vNearPos ); if ( iMyNode == NO_NODE ) { Vector pos = GetOuter()->GetAbsOrigin(); DevWarning( 2, "FindCover() - %s has no nearest node! (Check near %f %f %f)\n", GetEntClassname(), pos.x, pos.y, pos.z); return NO_NODE; } if ( !flMaxDist ) { // user didn't supply a MaxDist, so work up a crazy one. flMaxDist = 784; } if ( flMinDist > 0.5 * flMaxDist) { flMinDist = 0.5 * flMaxDist; } // ------------------------------------------------------------------------------------ // We're going to search for a cover node by expanding to our current node's neighbors // and then their neighbors, until cover is found, or all nodes are beyond MaxDist // ------------------------------------------------------------------------------------ AI_NearNode_t *pBuffer = (AI_NearNode_t *)stackalloc( sizeof(AI_NearNode_t) * GetNetwork()->NumNodes() ); CNodeList list( pBuffer, GetNetwork()->NumNodes() ); CVarBitVec wasVisited(GetNetwork()->NumNodes()); // Nodes visited // mark start as visited list.Insert( AI_NearNode_t(iMyNode, 0) ); wasVisited.Set( iMyNode ); float flMinDistSqr = flMinDist*flMinDist; float flMaxDistSqr = flMaxDist*flMaxDist; static int nSearchRandomizer = 0; // tries to ensure the links are searched in a different order each time; // Search until the list is empty while( list.Count() ) { // Get the node that is closest in the number of steps and remove from the list int nodeIndex = list.ElementAtHead().nodeIndex; list.RemoveAtHead(); CAI_Node *pNode = GetNetwork()->GetNode(nodeIndex); Vector nodeOrigin = pNode->GetPosition(GetHullType()); float dist = (vNearPos - nodeOrigin).LengthSqr(); if (dist >= flMinDistSqr && dist < flMaxDistSqr) { Activity nCoverActivity = GetOuter()->GetCoverActivity( pNode->GetHint() ); Vector vEyePos = nodeOrigin + GetOuter()->EyeOffset(nCoverActivity); if ( GetOuter()->IsValidCover( nodeOrigin, pNode->GetHint() ) ) { // Check if this location will block the threat's line of sight to me if (GetOuter()->IsCoverPosition(vThreatEyePos, vEyePos)) { // -------------------------------------------------------- // Don't let anyone else use this node for a while // -------------------------------------------------------- pNode->Lock( 1.0 ); if ( pNode->GetHint() && ( pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_MED || pNode->GetHint()->HintType() == HINT_TACTICAL_COVER_LOW ) ) { if ( GetOuter()->GetHintNode() ) { GetOuter()->GetHintNode()->Unlock(GetOuter()->GetHintDelay(GetOuter()->GetHintNode()->HintType())); GetOuter()->SetHintNode( NULL ); } GetOuter()->SetHintNode( pNode->GetHint() ); } // The next NPC who searches should use a slight different pattern nSearchRandomizer = nodeIndex; DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 255, 0 ); return nodeIndex; } else { DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 255, 0, 0 ); } } else { DebugFindCover( pNode->GetId(), vEyePos, vThreatEyePos, 0, 0, 255 ); } } // Add its children to the search list // Go through each link // UNDONE: Pass in a cost function to measure each link? for ( int link = 0; link < GetNetwork()->GetNode(nodeIndex)->NumLinks(); link++ ) { int index = (link + nSearchRandomizer) % GetNetwork()->GetNode(nodeIndex)->NumLinks(); CAI_Link *nodeLink = GetNetwork()->GetNode(nodeIndex)->GetLinkByIndex(index); if ( !m_pPathfinder->IsLinkUsable( nodeLink, iMyNode ) ) continue; int newID = nodeLink->DestNodeID(nodeIndex); // If not already on the closed list, add to it and set its distance if (!wasVisited.IsBitSet(newID)) { // Don't accept climb nodes or nodes that aren't ready to use yet if ( GetNetwork()->GetNode(newID)->GetType() != NODE_CLIMB && !GetNetwork()->GetNode(newID)->IsLocked() ) { // UNDONE: Shouldn't we really accumulate the distance by path rather than // absolute distance. After all, we are performing essentially an A* here. nodeOrigin = GetNetwork()->GetNode(newID)->GetPosition(GetHullType()); dist = (vNearPos - nodeOrigin).LengthSqr(); // use distance to threat as a heuristic to keep AIs from running toward // the threat in order to take cover from it. float threatDist = (vThreatPos - nodeOrigin).LengthSqr(); // Now check this node is not too close towards the threat if ( dist < threatDist * 1.5 ) { list.Insert( AI_NearNode_t(newID, dist) ); } } // mark visited wasVisited.Set(newID); } } } // We failed. Not cover node was found // Clear hint node used to set ducking GetOuter()->ClearHintNode(); return NO_NODE; }
void CNFMgr::convertFormulaToCNF(const ASTNode& varphi, ClauseList* defs) { CNFInfo* x = info[varphi]; //######################################## // divert to special case if term (word-level cnf) if (isTerm(*x)) { convertTermForCNF(varphi, defs); setWasVisited(*x); return; } //######################################## // do work if (sharesPos(*x) > 0 && !wasVisited(*x)) { convertFormulaToCNFPosCases(varphi, defs); } #if defined CRYPTOMINISAT__2 if ((x->clausespos != NULL && (x->clausespos->size() > 1 || (renameAllSiblings && !(x->clausespos->size() == 1 && x->clausespos[0].size() ==1) && !wasRenamedPos(*x))) || (doRenamePos(*x) && !wasVisited(*x)))) { if (doSibRenamingPos(*x) || sharesPos(*x) > 1 || doRenamePos(*x) || renameAllSiblings) { doRenamingPos(varphi, defs); } } #else if (x->clausespos != NULL && (x->clausespos->size() > 1 || (renameAllSiblings && !(x->clausespos->size() == 1 && x->clausespos[0].size() ==1) && !wasRenamedNeg(*x)))) { if (doSibRenamingPos(*x) || sharesPos(*x) > 1 || renameAllSiblings) { doRenamingPos(varphi, defs); } } #endif if (sharesNeg(*x) > 0 && !wasVisited(*x)) { convertFormulaToCNFNegCases(varphi, defs); } if (x->clausesneg != NULL && (x->clausesneg->size() > 1 || (renameAllSiblings && !(x->clausesneg->size() == 1 && x->clausesneg[0].size() ==1) && !wasRenamedNeg(*x)))) { if (doSibRenamingNeg(*x) || sharesNeg(*x) > 1 || renameAllSiblings) { doRenamingNeg(varphi, defs); } } //######################################## //mark that we've already done the hard work if(renameAllSiblings) { assert(info[varphi]->clausesneg == NULL || info[varphi]->clausesneg->size() ==1); assert(info[varphi]->clausespos == NULL || info[varphi]->clausespos->size() ==1); } setWasVisited(*x); } //End of convertFormulaToCNF()
void CRewardableObject::onHeroVisit(const CGHeroInstance *h) const { auto grantRewardWithMessage = [&](int index) -> void { auto vi = getVisitInfo(index, h); logGlobal->debugStream() << "Granting reward " << index << ". Message says: " << vi.message.toString(); // show message only if it is not empty if (!vi.message.toString().empty()) { InfoWindow iw; iw.player = h->tempOwner; iw.soundID = soundID; iw.text = vi.message; vi.reward.loadComponents(iw.components, h); cb->showInfoDialog(&iw); } // grant reward afterwards. Note that it may remove object grantReward(index, h); }; auto selectRewardsMessage = [&](std::vector<ui32> rewards) -> void { BlockingDialog sd(canRefuse, rewards.size() > 1); sd.player = h->tempOwner; sd.soundID = soundID; sd.text = onSelect; for (auto index : rewards) sd.components.push_back(getVisitInfo(index, h).reward.getDisplayedComponent(h)); cb->showBlockingDialog(&sd); }; if(!wasVisited(h)) { auto rewards = getAvailableRewards(h); bool objectRemovalPossible = false; for(auto index : rewards) { if(getVisitInfo(index, h).reward.removeObject) objectRemovalPossible = true; } logGlobal->debugStream() << "Visiting object with " << rewards.size() << " possible rewards"; switch (rewards.size()) { case 0: // no available rewards, e.g. empty flotsam { InfoWindow iw; iw.player = h->tempOwner; iw.soundID = soundID; if (!onEmpty.toString().empty()) iw.text = onEmpty; else iw.text = onVisited; cb->showInfoDialog(&iw); break; } case 1: // one reward. Just give it with message { if (canRefuse) selectRewardsMessage(rewards); else grantRewardWithMessage(rewards[0]); break; } default: // multiple rewards. Act according to select mode { switch (selectMode) { case SELECT_PLAYER: // player must select selectRewardsMessage(rewards); break; case SELECT_FIRST: // give first available grantRewardWithMessage(rewards[0]); break; case SELECT_RANDOM: // select one randomly //TODO: use weights grantRewardWithMessage(rewards[CRandomGenerator::getDefault().nextInt(rewards.size()-1)]); break; } break; } } if(!objectRemovalPossible && getAvailableRewards(h).size() == 0) { ChangeObjectVisitors cov(ChangeObjectVisitors::VISITOR_ADD_TEAM, id, h->id); cb->sendAndApply(&cov); } } else { logGlobal->debugStream() << "Revisiting already visited object"; InfoWindow iw; iw.player = h->tempOwner; iw.soundID = soundID; if (!onVisited.toString().empty()) iw.text = onVisited; else iw.text = onEmpty; cb->showInfoDialog(&iw); } }
std::string CRewardableObject::getHoverText(const CGHeroInstance * hero) const { if(visitMode != VISIT_UNLIMITED) return getObjectName() + " " + visitedTxt(wasVisited(hero)); return getObjectName(); }
std::string CRewardableObject::getHoverText(PlayerColor player) const { if(visitMode == VISIT_PLAYER || visitMode == VISIT_ONCE) return getObjectName() + " " + visitedTxt(wasVisited(player)); return getObjectName(); }