home *** CD-ROM | disk | FTP | other *** search
/ AI Game Programming Wisdom / AIGameProgrammingWisdom.iso / SourceCode / 07 DecisionMaking Architectures / 01 Isla, Blumberg / DefenseTactician.java < prev    next >
Encoding:
Java Source  |  2001-09-25  |  5.2 KB  |  153 lines

  1. package bb;
  2.  
  3. import java.awt.*;
  4. import java.util.*;
  5. import javax.swing.*;
  6. import java.awt.geom.*;
  7.  
  8. /*
  9. The DefenseTactician is a unit that analyses the battle and posts missions 
  10. which prompt commanders and their squads to defend strategically
  11. important areas.
  12.  
  13. It does this by receiving notifications of its team members' deaths. The more
  14. deaths that occur in a single area them more important it is to defend that
  15. area. This is a simple little home-brewed, half-baked clustering algorithm.
  16. Whenever a team-mate dies, a cluster is sought to "explain" that death (a 
  17. cluster simply being a circular area of land defined by a center and a 
  18. radius). If the death location lies inside a pre-existing cluster, then that
  19. cluster's radius is shrunk slightly. If the death location does NOT lie
  20. within an existing cluster, a new cluster is created.
  21.  
  22. This clustering system is entirely internal to the defense tactician, so 
  23. no one else knows about it. For each cluster a corresponding DEFEND_LOCATION
  24. mission is posted. The priority of the mission is inversely proportional to
  25. the cluster's radius. i.e. a small tight cluster will be very high priority.
  26. The cluster's radius also grows gradually over time, and the cluster will
  27. eventually be removed if no deaths have occured there for a long time
  28. (indicating that the cluster no longer represents a strategically
  29. important area).
  30.  
  31. Interestingly, the defense tactician is an important unit, but it also has a 
  32. physical body. So if one team manages to kill the other's defense tactician, 
  33. then all this cluster-based tactics is lost and the army begins to act
  34. stupidly.
  35.  
  36. @author naimad
  37. */
  38.  
  39. public class DefenseTactician extends Agent implements EventNotifier {
  40.  
  41.     public final static int COST = 500;
  42.  
  43.     public DefenseTactician(int team, Vec2 pos, Blackboard bb, World world) {
  44.         super(team, 5, pos, 5.0, 20.0, 10000.0, bb, world);
  45.         
  46.         world.addEventNotifier(team, this);
  47.  
  48.         defaultSkill = null;
  49.     }
  50.  
  51.     /*
  52.     Update the clusters.
  53.     */
  54.     public void actionExecute(double time) {
  55.         for (int c=0; c < clusters.size();c++) {
  56.             Cluster cluster = (Cluster)clusters.elementAt(c);
  57.             cluster.update(time);
  58.             if (cluster.weight < 0.1) {
  59.                 cluster.remove();
  60.                 clusters.removeElement(cluster);
  61.                 c--;
  62.             }
  63.         }
  64.     }
  65.     
  66.     Shape clusterShape;
  67.     public Shape createShape() {
  68.         clusterShape = new Ellipse2D.Double(-50.0, -50.0, 100.0, 100.0);
  69.         return new Ellipse2D.Double(-5.0, -5.0, 10.0, 10.0);
  70.     }
  71.  
  72.     public void updateGraphics(double time, Graphics2D g2) {
  73.         g2.translate(pos.x(), pos.y());
  74.         drawShape(time, g2);
  75.         g2.translate(-pos.x(), -pos.y());
  76.         
  77.         //Optionally, draw each of my clusters...
  78.         /*
  79.         for (int c=0; c < clusters.size(); c++) {
  80.             Cluster cluster = (Cluster)clusters.elementAt(c);
  81.             g2.translate(cluster.center.x(), cluster.center.y());
  82.             ((Ellipse2D.Double)clusterShape).setFrame(-cluster.radius, -cluster.radius, 2*cluster.radius, 2*cluster.radius);
  83.             g2.draw(clusterShape);
  84.             g2.translate(-cluster.center.x(), -cluster.center.y());
  85.         }
  86.         */
  87.     }
  88.     
  89.     //-------------------EventNotification Interface-------------------
  90.     
  91.     Vector clusters = new Vector();
  92.     
  93.     //The call-back we get when a fellow team-mate is killed.
  94.     public void deathNotification(Agent a, Vec2 location) {
  95.         boolean clusterFound = false;
  96.         for (int c=0; c < clusters.size(); c++) {
  97.             Cluster cluster = (Cluster)clusters.elementAt(c);
  98.             if (cluster.inside(location)) {
  99.                 clusterFound = true;
  100.                 cluster.addExample(location);   
  101.             }
  102.         }
  103.         if (!clusterFound) {
  104.             Cluster newc = new Cluster(location);
  105.             newc.addExample(location);   
  106.             clusters.addElement(newc);
  107.         }
  108.     }
  109.  
  110.     //The convenience class representing a cluster.
  111.     
  112.     class Cluster {
  113.         double radius = 50.0;
  114.         Vec2 center;
  115.         double weight = -0.5;
  116.         double fconst = 0.9;
  117.         
  118.         LocatableMission mission;
  119.         
  120.         public Cluster(Vec2 center) {
  121.             this.center = new Vec2(center);
  122.             mission = new LocatableMission(Commander.DefendLocationSkill.DEFENDLOCATION, 1, 0, center);
  123.             bb.addMission(mission);
  124.         }
  125.         
  126.         public boolean inside(Vec2 loc) {
  127.             return (loc.distance(center) < radius);
  128.         }
  129.         
  130.         public void update(double time) {
  131.             weight *= 0.98;
  132.             radius = 200.0/(2.5+weight);
  133.         }
  134.         
  135.         Vec2 temp = new Vec2();
  136.         public void addExample(Vec2 location) {
  137.             weight+=1.0;
  138.             center.scale(fconst);
  139.             temp.set(location);
  140.             temp.scale(1-fconst);
  141.             Vec2.add(center, temp, center);
  142.             
  143.             mission.setPriority(weight);
  144.             mission.setTargetPosition(center);
  145.         }
  146.         
  147.         public void remove() {
  148.             mission.setMissionComplete();
  149.             bb.removeMission(mission);
  150.         }
  151.     }
  152. }
  153.