النمل الأبيض

كتبتُ صنفاً باسم Termite يوسع الصنف Bug ويضيف له القدرة على التفاعل مع الأزهار.
لتشغيله، نزل هذه الملفات واستوردها إلى بيئة البرمجة لديك:
http://thinklikecs.webs.com/resources/code/Termite.java
http://thinklikecs.webs.com/resources/code/Termite.gif
http://thinklikecs.webs.com/resource...iteRunner.java
بما أن Termite يوسع Bug، كل عمليات Bug ستعمل على Termite. لكن النمل الأبيض (Termites) يملك عمليات إضافية لا تملكها الحشرات (Bugs).
كود:
/**
 * Returns true if the termite has a flower.
 */
public boolean hasFlower();
 
/**
 * Returns true if the termite is facing a flower.
 */
public boolean seeFlower();
 
/**
 * Creates a flower unless the termite already has one.
 */
public void createFlower();
 
/**
 * Drops the flower in the termites current location.
 *
 * Note: only one Actor can occupy a grid cell, so the effect of
 * dropping a flower is delayed until the termite moves.
 */
public void dropFlower();
 
/**
 * Throws the flower into the location the termite is facing.
 *
 */
public void throwFlower();
 
/**
 * Picks up the flower the termite is facing, if there is one,
 * and if the termite doesn't already have a flower.
 */
public void pickUpFlower();
بالنسبة لبعض العمليات، يوفر الصنف Bug تعريفاً لها ويوفر Termite لها تعريفاً آخر. في تلك الحالة، يجب أن تهيمن (override) عملية Termite على عملية Bug.
مثلاً، تعيد العملية Bug.canMove القيمة true إذا وجدت زهرة في الموقع التالي، لذا يمكن للحشرات أن تدوس الأزهار. أما Termite.canMove فتعيد false إذا وجد أي كائن في الموقع التالي، لذا فإن سلوك النمل الأبيض مختلف.
كمثال آخر، يملك النمل الأبيض نسخة من turn تأخذ عدداً صحيحاً من الدرجات كمعامل. أخيراً، يملك النمل الأبيض randomTurn، التي تدوره 45 درجة على اليمين أو اليسار عشوائياً.
ها هي الشفرة من TermiteRunner.java:
كود:
public class TermiteRunner
{
 
   public static void main(String[] args)
   {
 
   ActorWorld world = new ActorWorld();
   makeFlowers(world, 20);
 
   Termite alice = new Termite();
   world.add(alice);
 
   Termite bob = new Termite();
   bob.setColor(Color.blue);
   world.add(bob);
 
   world.show();
   }
 
   public static void makeFlowers(ActorWorld world, int n) {
      for (int i=0; i<n; i++) {
         world.add(new EternalFlower());
      }
   }
}
يجب أن يبدو كل شيء هنا مألوفاً. يقوم TermiteRunner بإنشاء ActorWorld فيه عشرين زهرة خارجية (ExternalFlower) ونملتين بيضاوين (two Termites).
الزهرة الخارجية هي زهرة تتجاهل العملية act حتى لا تصبح الأزهار أغمق.
كود:
class EternalFlower extends Flower {
   public void act() {}
}
إذا شغلت TermiteRunner.java يجب أن ترى نملتين تتحركان عشوائياً بين الأزهار.
يوضح MyTermite.java العمليات التي تتفاعل مع الأزهار. ها هو تعريف الصنف:
كود:
public class MyTermite extends Termite {
   public void act() {
 
      if (getGrid() == null)
         return;
 
      if (seeFlower()) {
         pickUpFlower();
      }
 
      if (hasFlower()) {
         dropFlower();
      }
 
      if (canMove()) {
         move();
      }
 
      randomTurn();
   }
}
MyTermite يوسع Termite، ويتجاوز العملية act. إذا رأت MyTermite زهرة، ستلتقطها، وإذا كانت تملك زهرة، ستتركها.

تمرين 10.2

الغرض من هذا التمرين هو اسكتشاف سلوك النمل الأبيض الذي يتفاعل مع الأزهار.
عدل TermiteRunner.java لإنشاء MyTermites بدلاً من Termites. بعدها شغله ثانية. يجب أن تتحرك MyTermites عشوائياً، محركة الأزهار. يجب ألا يتغير عدد الأزهار (بما في ذلك الأزهار التي تمسكها MyTermites).
في كتاب Termites, Turtles and Traffic Jams يصف الكاتب Mitchell Resnick نمطاً بسيطاً من سلوك النمل الأبيض:
· إذا شاهدت زهرة، التقطها. إلا إذا كنت تملك زهرة من قبل؛ في تلك الحالة، ارم الزهرة التي معك.
· تحرك للأمام إذا استطعت.
· استدر يميناً أو يساراً بشكل عشوائي.
عدل MyTermite.java لتنفيذ هذا النمط. ما أثر هذا التعديل على سلوك MyTermites برأيك؟
جربه. يجب ألا يتغير عدد الأزهار أيضاً، لكن مع الوقت ستتكدس الأزهار في عدد قليل من الكوم، على الأغلب كومة واحدة فقط.
هذا السلوك هو صفة متطورة (emergent property)، التي تستطيع أن تقرأ عنها في http://en.wikipedia.org/wiki/Emergence. تتبع MyTermites قوعد بسيطة معتمدة على معلومات قصيرة المدى، لكن النتيجة هي منظمة كبيرة الحجم.