[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[crimson-list] Improve AI behavior : transport



A new patch for crimson !

AI sucks with transport ! It currently only use transport when no other way to reach the target is available ; with this patch, the AI check if a transport allow to reach the target quicker. The unit stay in the transport as long it give an advantage instead of moving to the target by its own.

There is a little level test wich show the problem.

--
Sébastien
diff -urNp crimson-0.5.3_orig/src/cf/ai.cpp crimson-0.5.3_patch/src/cf/ai.cpp
--- crimson-0.5.3_orig/src/cf/ai.cpp	2007-01-20 11:19:26.000000000 +0100
+++ crimson-0.5.3_patch/src/cf/ai.cpp	2014-04-13 17:27:49.000000000 +0200
@@ -1059,39 +1059,77 @@ bool AI::UnitGoTo( Unit *u, const Point
   Path p( map );
   Point end;
 
-  if ( p.Find( u, u->Position(), dest, PATH_BEST, dist ) != -1 ) {
-    end = FollowPath( u, p );
-    Gam->MoveUnit( u, end );
-  } else {
+  const bool sheltered = u->IsSheltered();
+
+  u->UnsetFlags( U_SHELTERED );
+  short distance = p.Find( u, u->Position(), dest, PATH_BEST, dist );
+  if (sheltered) u->SetFlags( U_SHELTERED );
+
+  Transport *t = FindTransport( u, dest, dist, true );
+
+  if ( distance == -1 ) {
     // try to find a way using a transporter
-    short turns;
-    Transport *t = FindTransport( u, dest, dist, true );
-    if ( t ) {
-      turns = p.Find( u, u->Position(), t->Position() );
-      if ( (turns != 1) && (t->UnitCount() == 0) ) {
-        // get the transport closer first (only if it's empty)
-        TransPath tp( map, t );
-        if ( tp.Find( u, t->Position(), u->Position() ) != -1 ) {
-          Gam->SelectUnit( t );
-          end = FollowPath( t, tp, 1 );
-          Gam->MoveUnit( t, end );
-          Gam->SelectUnit( u );
-
-          turns = p.Find( u, u->Position(), end );
-          if ( turns != -1 ) {
-            end = FollowPath( u, p );
-            Gam->MoveUnit( u, end );
-          } else {
-            tp.Reverse();
-            end = FollowPath( u, tp );
-            Gam->MoveUnit( u, end );
-          }
+    if ( !t ) {
+      return false;
+    }
+    short turns = p.Find( u, u->Position(), t->Position() );
+    if ( (turns != 1) && (t->UnitCount() == 0) ) {
+      // get the transport closer first (only if it's empty)
+      TransPath tp( map, t );
+      if ( tp.Find( u, t->Position(), u->Position() ) != -1 ) {
+        Gam->SelectUnit( t );
+        end = FollowPath( t, tp, 1 );
+        Gam->MoveUnit( t, end );
+        Gam->SelectUnit( u );
+
+        turns = p.Find( u, u->Position(), end );
+        if ( turns != -1 ) {
+          end = FollowPath( u, p );
+          Gam->MoveUnit( u, end );
+        } else {
+          tp.Reverse();
+          end = FollowPath( u, tp );
+          Gam->MoveUnit( u, end );
         }
-      } else if ( turns >= 0 ) {
-        end = FollowPath( u, p );
+      }
+    } else if ( turns >= 0 ) {
+      end = FollowPath( u, p );
+      Gam->MoveUnit( u, end );
+    }
+  } else {
+    // The unit could get this point by is own, but we check if it could be
+    // better by using a transport
+    if ( !t || distance <= 2
+        || !t->Allow( u )) {
+      end = FollowPath( u, p );
+      Gam->MoveUnit( u, end );
+      return true;
+    }
+    TransPath tp( map, t );
+    Path p2( map );
+    short turnsToTarget = tp.Find( t, dest, t->Position() );
+    short turnsToTransport = p2.Find( u, u->Position(), t->Position() );
+    if ( turnsToTransport != -1 && turnsToTarget != -1 
+        && turnsToTransport + turnsToTarget < distance) {
+      Gam->SelectUnit( t );
+      end = FollowPath( t, tp, 1 );
+      Gam->MoveUnit( t, end );
+      Gam->SelectUnit( u );
+
+      short turns = p2.Find( u, u->Position(), end );
+      if ( turns != -1 ) {
+        end = FollowPath( u, p2 );
+        Gam->MoveUnit( u, end );
+      } else {
+        tp.Reverse();
+        end = FollowPath( u, tp );
         Gam->MoveUnit( u, end );
       }
-    } else rc = false;
+    } else {
+      end = FollowPath( u, p );
+      Gam->MoveUnit( u, end );
+      return true;
+    }
   }
   return rc;
 }

Attachment: test_02.lev
Description: Binary data