Change method

edited March 2017 in How To...

Hello,
I am working on a game I abbandoned a long time ago in a different language (Algoid). My question: I have a class Bot and inside a method void AI(). I want to change the AI of the bots based on their type. Is there any way to change a method?

Answers

  • switch (type) {
       ...
    }
    

    alternatively, give all the different types classes of their own, have them extend Bot class and each override the AI() method.

  • edited March 2017

    1st of all, by convention, variables & functions in Java & JS follow the lowerUpperCase naming rule.
    So your method AI() should be renamed as ai(). :\">

    Java & JS allow us to create subclasses w/ keyword extends:
    https://Processing.org/reference/extends.html

    There are other approaches such as abstract class & interface:
    https://Processing.org/reference/implements.html

    In case each Bot should have its own distinguished ai() behavior, a much more practical approach is to implement it at the same time Bot is instantiated:

    // forum.Processing.org/two/discussion/21321/change-method#Item_2
    // GoToLoop (2017-Mar-10)
    
    static final int BOTS = 3;
    final Bot[] bots = new Bot[BOTS];
    
    void setup() {
      size(500, 400);
      noLoop();
    
      noStroke();
      rectMode(CORNER);
      ellipseMode(CENTER);
    
      createBots();
    }
    
    void draw() {
      background(0);
      for (final Bot b : bots)  b.ai();
    }
    
    void createBots() {
      final int x2 = width  >> 1, x3 = width  / 3;
      final int h2 = height >> 1, h3 = height / 3;
    
      bots[0] = new Bot(25, h2 - h3/2, h3, #0000FF) {
        @ Override public void ai() {
          fill(c);
          rect(x, y, d, d);
        }
      };
    
      bots[1] = new Bot(x2, h2, h3, #FFFF00) {
        @ Override public void ai() {
          fill(c);
          ellipse(x, y, d, d);
        }
      };
    
      bots[2] = new Bot(2*x3, h2 - h3/2, h3, #FF0000) {
        @ Override public void ai() {
          fill(c);
          rect(x, y, d, d*1.5);
        }
      };
    }
    
    public abstract class Bot {
      public int x, y, d, c;
    
      public Bot(int px, int py, int pd, color pc) {
        x = px;
        y = py;
        d = pd;
        c = pc;
      }
    
      abstract void ai();
    }
    
  • ick.

    anonymous methods only make sense if they are small. nothing in the name ai() suggests small.

  • edited March 2017

    First of all, thank you for the replies.

    Well, the ai() is small (I think). I have 3 types of bots at the moment:

    Target Bot:

    Fastest Bot.

    This Bot has the most complex AI.

    I called it the Target Bot, because I couldn't come up with a better name.

    Wants to stay near Friendly Bot, avoids Enemy Bot. Avoiding Enemy Bot is more important than staying near Friendly Bot.

    When all Target Bots are killed, the simulation ends.

    Does not respawn by itself. If at least one Target Bot in reach of at least one Friendly Bot and out of reach of any Enemy Bot is nearby, revive points are added to the dead Target Bot and small damage is applied to the living Target Bot. (No Friendly Bots need to be in reach and any Enemy Bots can be in reach of the dead Target Bot.) The more Friendly Bots are near the living Target Bot, the more revive points are added to the dead Target Bot and the more damage is applied to the living Target Bot. (Regardless of the living Target Bot's HP this will not kill the living Target Bot.) Once the dead Target Bot has enough revive points, it respawns on the same place it died regardless of the position of any Enemy Bot. It respawns with half HP, but with higher resistance. (Regardless of the Target Bot's resistance, the Target Bot will always recieve at least 1 Damage Point per tick when in reach of an Enemy Bot.) The Target Bots don't seek dead Target Bots. (I might change that.)

    Friendly Bot:

    Slowest Bot.

    Basically always tries to go to random positions.

    Infinite HP (Nothing damages it).

    Heals Target Bot, damages Enemy Bot.

    Enemy Bot:

    A little faster than Friendly Bot, but slower than Target Bot.

    Follows the Target Bot, or better said, tries to get near the Target Bot. Doesn't avoid Friendly Bot.

    Much less HP than Target Bot, a little smaller reach than Friendly Bot.

    Target Bot wants to avoid any of these Bots. Avoiding these Bots has a higher priority than staying near a Friendly Bot.

    When killed, respawns on a random place out of reach of any Friendly Bot and with a little more HP than it had before.

    The goal of the Target Bots is to stay alive as long as possible.

    So, the ai() is small for Enemy and Friendly Bots, but for the Target Bots it is huge. I only need to change the ai() at the beginning of a simulation. There is only one simulation per run of the program.

    I only have a single ArrayList for all bots. Is it possible to create 3 Bots at the beginning, one for each type, as a kind of blueprint, then change the ai() for each one of them and then just copy them to the ArrayList used in the simulation? Would it work for multiple simulations in a single run of the program?

  • edited April 2017 Answer ✓

    Since I didn't know yet how many different AI bots there would be, my mock code relied on anonymous instantiations; in which abstract methods are implemented in loco, at the same time their class is instantiated. L-)

    But now that you've finally revealed to us you need exactly 3 different AI types of Bot classes, the best strategy is turn them all as 3 subclasses inheriting from base class Bot: :\">

    // https://forum.Processing.org/two/discussion/21321/change-method#Item_5
    // GoToLoop (2017-Mar-31)
    
    static final int BOTS = 3;
    final Bot[] bots = new Bot[BOTS];
    
    void setup() {
      size(500, 400);
      noLoop();
    
      noStroke();
      rectMode(CORNER);
      ellipseMode(CENTER);
    
      createBots();
    }
    
    void draw() {
      clear();
      for (final Bot b : bots)  b.ai();
    }
    
    void createBots() {
      final int x2 = width  >> 1, x3 = width  / 3;
      final int h2 = height >> 1, h3 = height / 3;
    
      bots[0] = new TargetBot(25, h2 - h3/2, h3, #0000FF);
      bots[1] = new FriendlyBot(x2, h2, h3, #FFFF00);
      bots[2] = new EnemyBot(2*x3, h2 - h3/2, h3, #FF0000);
    }
    
    abstract class Bot {
      int x, y, d, c;
    
      Bot(int px, int py, int pd, color pc) {
        x = px;
        y = py;
        d = pd;
        c = pc;
      }
    
      abstract void ai();
    }
    
    class TargetBot extends Bot {
      TargetBot(int x, int y, int d, color c) {
        super(x, y, d, c);
      }
    
      @Override void ai() {
        fill(c);
        rect(x, y, d, d);
      }
    }
    
    class FriendlyBot extends Bot {
      FriendlyBot(int x, int y, int d, color c) {
        super(x, y, d, c);
      }
    
      @Override void ai() {
        fill(c);
        ellipse(x, y, d, d);
      }
    }
    
    class EnemyBot extends Bot {
      EnemyBot(int x, int y, int d, color c) {
        super(x, y, d, c);
      }
    
      @Override void ai() {
        fill(c);
        rect(x, y, d, d*1.5);
      }
    }
    
  • edited April 2017

    Wow, thank you. I didn't know I could put an extension of Bot inside array of type Bot. Thanks! :)

  • @TheUltimateKrtek --

    This discussion might help: http://stackoverflow.com/a/36117157

    Objects in Java are polymorphic: You can simply declare an array of a common base type and have objects of all kinds of derived classes in it.

    Number[] foo = {new Integer(0), new Double(1), new Long(2), ...};

    In Processing, this means for example that an array of PImage[] can hold a mix of PImage and PGraphics objects.

  • And Capture and Video.

  • I can't use methods in the class FriendlyBot, if they aren't in the class Bot.

Sign In or Register to comment.