@@ -160,6 +160,8 @@ void AggroBAIState::exit()
160160 */
161161void AggroBAIState::think (BattleAction *action)
162162{
163+ if (Options::getBool (" traceAI" )) { Log (LOG_INFO ) << " AggroBAIState::think() #" << action->number ; }
164+
163165 action->type = BA_RETHINK ;
164166 action->actor = _unit;
165167 /* Aggro is mainly either shooting a target or running towards it (melee).
@@ -387,11 +389,19 @@ void AggroBAIState::think(BattleAction *action)
387389 if (aggression == 2 && number < 90 )
388390 takeCover = false ;
389391
390- if (action->number == 2 )
391- {
392+ if (action->number >= 3 )
393+ {
394+ if (_unit->_hidingForTurn )
395+ {
396+ // already tried to get to cover; stay still
397+ action->type = BA_NONE ;
398+ action->TU = 0 ;
399+ return ;
400+ }
401+
392402 takeCover = true ; // always seek cover as last action
393403 action->reckless = true ;
394- }
404+ }
395405
396406 // we're using melee, so CHAAAAAAAARGE!!!!!
397407 if (_unit->getMainHandWeapon () && _unit->getMainHandWeapon ()->getRules ()->getBattleType () == BT_MELEE )
@@ -423,8 +433,8 @@ void AggroBAIState::think(BattleAction *action)
423433 _game->getPathfinding ()->calculate (action->actor , checkPath, 0 );
424434 int newDistance = _game->getTileEngine ()->distance (action->actor ->getPosition (), checkPath);
425435 bool valid = _game->getTileEngine ()->validMeleeRange (checkPath, -1 , action->actor ->getArmor ()->getSize (), action->actor ->getHeight (), _aggroTarget);
426- if (_game->getPathfinding ()->getStartDirection () != -1 /* && valid &&
427- newDistance < distance*/ )
436+ if (_game->getPathfinding ()->getStartDirection () != -1 && valid &&
437+ newDistance < distance)
428438 {
429439 // CHAAAAAAARGE!
430440 action->target = checkPath;
@@ -517,6 +527,7 @@ void AggroBAIState::think(BattleAction *action)
517527 // if there is no such tile, we run away from the target.
518528 bool sneak = Options::getBool (" sneakyAI" );
519529 action->type = BA_WALK ;
530+ _unit->_hidingForTurn = true ;
520531 int tries = 0 ;
521532 bool coverFound = false ;
522533 int x_search_sign = RNG::generate (0 , 1 ) ? 1 : -1 ; // randomize the direction of the search for lack of a better heuristic
@@ -533,32 +544,50 @@ void AggroBAIState::think(BattleAction *action)
533544 int score = -1000 ;
534545 Position bestTile (0 , 0 , 0 );
535546 ++_randomTileSearchAge;
547+ if (action->number > 1 ) action->desperate = true ;
548+
549+ Tile *tile = 0 ;
550+
536551
537552 while (tries < 150 && !coverFound)
538553 {
539554 tries++;
540555 action->target = _unit->getPosition () + run; // start looking in a direction away from the enemy
556+
557+ if (!_game->getTile (action->target ))
558+ {
559+ action->target = _unit->getPosition (); // cornered at the edge of the map perhaps?
560+ }
561+
541562 if (tries < 121 )
542563 {
543564 // looking for cover
544565 action->target .x += _randomTileSearch[tries].x ;
545566 action->target .y += _randomTileSearch[tries].y ;
546- if (action->target == _unit->getPosition () && unitsSpottingMe > 0 )
567+ if (action->target == _unit->getPosition () && action-> number == 1 && unitsSpottingMe > 0 )
547568 {
548569 // don't even think about staying in the same spot. Move!
549570 action->target .x += RNG::generate (-20 ,20 );
550571 action->target .y += RNG::generate (-20 ,20 );
551572 }
552- score = _game->getTileEngine ()->visible (_aggroTarget, _game->getTile (action->target )) ? 0 : 100 ;
573+ // score = _game->getTileEngine()->visible(_aggroTarget, _game->getTile(action->target)) ? 0 : 100;
574+ score = 100 ; // no need for visible here, the TileEngine code will take care of it
553575 }
554576 else
555577 {
556- if (tries == 121 ) Log (LOG_INFO ) << _unit->getId () << " best score after systematic search was: " << bestTileScore;
557- action->desperate = true ;
558- score = 130 ; // ruuuuuuun
559- action->target = _unit->getPosition () + run*2 ;
560- action->target .x += RNG::generate (-5 ,5 );
561- action->target .y += RNG::generate (-5 ,5 );
578+ if (tries == 121 )
579+ {
580+ action->reckless = true ;
581+ if (Options::getBool (" traceAI" ))
582+ {
583+ Log (LOG_INFO ) << _unit->getId () << " best score after systematic search was: " << bestTileScore;
584+ }
585+ }
586+
587+ score = 110 ; // ruuuuuuun
588+ action->target = _unit->getPosition () + run*3 ;
589+ action->target .x += RNG::generate (-10 ,10 );
590+ action->target .y += RNG::generate (-10 ,10 );
562591 action->target .z = _unit->getPosition ().z + RNG::generate (-1 ,1 );
563592 if (action->target .z < 0 )
564593 {
@@ -571,39 +600,51 @@ void AggroBAIState::think(BattleAction *action)
571600 }
572601
573602 // THINK, DAMN YOU
574- if (!_game->getPathfinding ()->bresenhamPath (_aggroTarget->getPosition (), action->target , 0 , false )) score += 25 ; // partial cover?
575- _game->getPathfinding ()->abortPath (); // clean up hypothetical path data
576- if (sneak)
603+ tile = _game->getTile (action->target );
604+ if (!tile)
577605 {
578- Tile *tile = _game->getTile (action->target );
579- if (!tile) score = -10000 ;
580- else if (tile->getVisible ()) score -= 50 ;
581- // XXX perhaps only psi-skilled aliens should cheat-sneak?
606+ score = -10000 ; // no you can't quit the battlefield by running off the map.
582607 }
583- score += abs (action->target .x - _aggroTarget->getPosition ().x );
584- score += abs (action->target .y - _aggroTarget->getPosition ().y );
585- score += abs (action->target .z - _aggroTarget->getPosition ().z )*2 ;
586-
587- int nearestEnemy = 1000 ; // too far away to matter
588- for (std::vector<BattleUnit*>::const_iterator i = _game->getUnits ()->begin (); i != _game->getUnits ()->end (); ++i)
608+ else
589609 {
590- if ((*i)->getId () == _unit->getId ()) continue ; // woo, it's us
591- if ((*i)->isOut ()) continue ; // derp
592- int distSq = _game->getTileEngine ()->distanceSq (action->target , (*i)->getPosition ());
593- if (distSq == 0 ) distSq = 1 ; // dont divide by 0
594- if (distSq <= 100 )
610+ if (sneak)
595611 {
596- if ((*i)->getFaction () == FACTION_PLAYER )
597- {
598- if (distSq < nearestEnemy) nearestEnemy = distSq;
599- } else
600- {
601- if (distSq <= 2 ) score += 5 ; // quick, hide behind the nearest civilian?
602- if (distSq <= 9 && (*i)->getFaction () == FACTION_HOSTILE ) score += 5 ; // strength in numbers?
603- }
612+ if (tile->getVisible ()) score -= 50 ;
613+ // XXX perhaps only psi-skilled aliens should cheat-sneak?
604614 }
615+
616+ _game->getTileEngine ()->surveyXComThreatToTile (tile, action->target , _unit);
617+
618+ if (tile->_soldiersVisible && tile->_closestSoldierDSqr <= 100 && tile->_closestSoldierDSqr > 0 ) score -= (200 /tile->_closestSoldierDSqr );
619+ // if (!tile->_soldiersVisible) { Log(LOG_WARNING) << "No soldiers visible? Really?"; }
620+
621+ if (!tile->_soldiersVisible )
622+ {
623+ score += dist*5 ; // hooray!
624+ } else
625+ {
626+ score -= tile->_soldiersVisible * 10 ;
627+ score += (dist > 9 ) ? 9 : dist;
628+ }
629+
630+ if (tile->_closestAlienDSqr < 25 && tile->_closestAlienDSqr > 4 ) score += 4 ; // strength in numbers but not in "grenade us!" huddles
631+
632+ _game->getPathfinding ()->setUnit (_unit); // because we can't just pass this around as a paramater, can we... no, that would be too simple
633+
634+ if (tile->_soldiersVisible && _game->getPathfinding ()->bresenhamPath (tile->_closestSoldierPos , action->target , 0 , false )) score -= 50 ; // not even partial cover?
635+ _game->getPathfinding ()->abortPath (); // clean up hypothetical path data
636+
637+ if (!_game->getPathfinding ()->bresenhamPath (_aggroTarget->getPosition (), action->target , 0 , false )) score += 4 ; // partial cover?
638+ _game->getPathfinding ()->abortPath (); // clean up hypothetical path data
639+
640+ if (tile->getFire ()) score -= 20 ;
641+
642+ if (tile->getSmoke ()) score -= 2 ;
643+
644+ if (tile->getMapData (MapData::O_NORTHWALL ) || tile->getMapData (MapData::O_WESTWALL )) score += 1 ; // hug the walls
645+
646+ if (_game->getTileEngine ()->faceWindow (action->target ) != -1 ) score -= 50 ; // a window is not cover.
605647 }
606- if (nearestEnemy < 100 ) score -= (100 -nearestEnemy);
607648
608649
609650 if (score > bestTileScore)
@@ -617,11 +658,15 @@ void AggroBAIState::think(BattleAction *action)
617658 bestTile = action->target ;
618659 }
619660 _game->getPathfinding ()->abortPath ();
620- if (bestTileScore > 130 ) coverFound = true ; // good enough, gogogo; this value is hand-tuned and subjective :(
661+ if (bestTileScore > 120 ) coverFound = true ; // good enough, gogogo; this value is hand-tuned and subjective :(
621662 }
622663 }
623- Log (LOG_INFO ) << _unit->getId () << " Taking cover with score " << bestTileScore << " after " << tries << " tries." ;
624- Log (LOG_INFO ) << " Walking " << _game->getTileEngine ()->distance (_unit->getPosition (), bestTile) << " squares or so." ;
664+ if (Options::getBool (" traceAI" ))
665+ {
666+ Log (LOG_INFO ) << _unit->getId () << " Taking cover with score " << bestTileScore << " after " << tries << " tries, at a tile spotted by " << ((tile=_game->getTile (bestTile)) ? tile->_soldiersVisible : -666 ) << " . Action #" << action->number ;
667+ // Log(LOG_INFO) << "Walking " << _game->getTileEngine()->distance(_unit->getPosition(), bestTile) << " squares or so.";
668+
669+ }
625670 action->target = bestTile;
626671 }
627672 }
0 commit comments