cant find a pattern to fit neatly - how to make a large number of monsters?

Discussion in 'Java' started by steve mathers, Jan 23, 2005.

  1. Hi , fairly new to OO design. Trying to solve a problem:

    problem:
    I want to make a large number of different monsters. what makes
    monsters different from each other is their 'abilities'. These could
    such things as carrying a weapon or magic item that allows them to
    perform an action, or something like an intrinsic resistance to attack
    with fire, or a temporary ability ability granted by a spell cast on
    them.

    * I want to be able to define different monster types and different
    ability types using as little memory as possible (mobile phone
    platform) - a hard coded table of abilities and then another table of
    monsters that lists which ability each monster has. Some sort of
    factory will have to create the monster given an index into this
    table. Thats not the hard part.

    * I want to be able to add new monsters and new abilities to the table
    without changing the inteface of the monster and ability class. I
    think this is the hard part.

    solution: At first thought, the decorator pattern seems right, but
    because abilities can come and go all the time, it seems to be
    unweildy.

    I think what I want to happen is that every time the monster has to do
    something that involves its characteristics which may be modified by
    abilities (such as fire resistance), or it wants to perform an
    optional action that an ability may bestow it with (such as hit
    something with a weapon), it should interogate its entire list of
    current abilities to see if they impact on that charicteristic or
    action. But how to structure that process in my design?

    Is there a particular pattern I should be looking at?

    thanks,

    Steve
     
    steve mathers, Jan 23, 2005
    #1
    1. Advertising

  2. steve mathers

    thufir Guest

    steve mathers wrote:
    > Hi , fairly new to OO design. Trying to solve a problem:

    [..]
    > I think what I want to happen is that every time the monster has to

    do
    > something that involves its characteristics which may be modified by
    > abilities (such as fire resistance), or it wants to perform an
    > optional action that an ability may bestow it with (such as hit
    > something with a weapon), it should interogate its entire list of
    > current abilities to see if they impact on that charicteristic or
    > action. But how to structure that process in my design?

    [..]

    That sounds very computationally intensive to me. Depending on the
    size of the table, mightn't that create more of a strain than keeping a
    mobs characteristics within a single object?

    I've always heard that it's better to focus on design first and
    performance second. As an alternative, what's wrong with a very simple
    mob composed different "parts," like FireResistance.

    --
    Thufir Hawat
     
    thufir, Jan 23, 2005
    #2
    1. Advertising

  3. steve mathers

    Guest

    performance not an issue in this application, but codebase size is.
    and it would be nice to be able to add new types of abilities and
    monsters to the system just by adding a few bytes to a table and a
    function or two to handle them, and then have a factory creatre them at
    runtime.


    example of the process I was thinking of:

    monster object: holds intrinsic characteristics and list of optional
    abiltiies

    ability object: enables monster to perform some function, and/or
    modifies some of its abilities.

    so there is a dependency there between monster and ability, but how to
    make it as weak as possible. The vector of change is definately more
    types of abilities, and more types of monsters.

    use case 1: monster makes a melee attack: it interrogates each of its
    abilities: are you my current melee weapon, and if so, what type and
    degree of damage do you do?

    use case 2: monster needs to use its SPEED characetristic to determine
    if it is its turn to act yet. it interogates all its current
    abilities: here is my current SPEED - modify it if you will.

    Perhaps there is a better system?



    thufir wrote:
    > steve mathers wrote:
    > > Hi , fairly new to OO design. Trying to solve a problem:

    > [..]
    > > I think what I want to happen is that every time the monster has to

    > do
    > > something that involves its characteristics which may be modified

    by
    > > abilities (such as fire resistance), or it wants to perform an
    > > optional action that an ability may bestow it with (such as hit
    > > something with a weapon), it should interogate its entire list of
    > > current abilities to see if they impact on that charicteristic or
    > > action. But how to structure that process in my design?

    > [..]
    >
    > That sounds very computationally intensive to me. Depending on the
    > size of the table, mightn't that create more of a strain than keeping

    a
    > mobs characteristics within a single object?
    >
    > I've always heard that it's better to focus on design first and
    > performance second. As an alternative, what's wrong with a very

    simple
    > mob composed different "parts," like FireResistance.
    >
    > --
    > Thufir Hawat
     
    , Jan 24, 2005
    #3
  4. steve mathers

    thufir Guest

    wrote:
    > performance not an issue in this application, but codebase size is.
    > and it would be nice to be able to add new types of abilities and
    > monsters to the system just by adding a few bytes to a table and a
    > function or two to handle them, and then have a factory creatre them

    at
    > runtime.


    If each monsters attributes are composed of different objects, it
    should be very easy make a SuperSword class and have
    bigMonster.armWith("superSword") I'd think.

    I don't know how to address your codebase size concern, sorry...

    > example of the process I was thinking of:
    >
    > monster object: holds intrinsic characteristics and list of optional
    > abiltiies


    instead of a list of abilities, try for objects :)

    > ability object: enables monster to perform some function, and/or
    > modifies some of its abilities.


    As in a sword object, or fireResistant object, of which a particular
    Monster type object would be composed. That is, each object would
    "have-a" object, or objects :)

    > so there is a dependency there between monster and ability, but how

    to
    > make it as weak as possible. The vector of change is definately more
    > types of abilities, and more types of monsters.


    Composition works very well at encapsulating data, which allows you to
    change dependant classes to a larger degree.

    > use case 1: monster makes a melee attack: it interrogates each of

    its
    > abilities: are you my current melee weapon, and if so, what type and
    > degree of damage do you do?


    public class BunchOfMonsters {
    public static void main (String args[]) {
    Creature blobMonster = new Monster("blob"); //"blob" is a
    monster type
    blobMonster.armWith("sword"); //sword is a type of weapon
    //have a list of monsters
    }
    }

    public class Monster implements Creature {
    public void armWith(String wep){
    if (wep == "sword") {
    Item aSword = new Sword(); } //give sword to monster
    instance
    //Sword implements Item
    }

    public void attack() {
    // find best weapon
    // find target
    }
    }


    > use case 2: monster needs to use its SPEED characetristic to

    determine
    > if it is its turn to act yet. it interogates all its current
    > abilities: here is my current SPEED - modify it if you will.


    how about each instance of Monster has an instance of Melee? Using
    Timer() each melee object determines when it gets to move. This object
    would then determine whether to fight or flee?

    > Perhaps there is a better system?


    <http://robocode.alphaworks.ibm.com/home/home.html>

    AFAIK this uses a "tick" idea, where there's a list of 'bots which gets
    iterated through once/sec; this is less complex than having a Melee
    class.


    --
    Thufir Hawat
     
    thufir, Jan 24, 2005
    #4
  5. steve mathers

    thufir Guest

    wrote:
    > performance not an issue in this application, but codebase size is.
    > and it would be nice to be able to add new types of abilities and
    > monsters to the system just by adding a few bytes to a table and a
    > function or two to handle them, and then have a factory creatre them

    at
    > runtime.


    If each monsters attributes are composed of different objects, it
    should be very easy make a SuperSword class and have
    bigMonster.armWith("superSword") I'd think.

    I don't know how to address your codebase size concern, sorry...

    > example of the process I was thinking of:
    >
    > monster object: holds intrinsic characteristics and list of optional
    > abiltiies


    instead of a list of abilities, try for objects :)

    > ability object: enables monster to perform some function, and/or
    > modifies some of its abilities.


    As in a sword object, or fireResistant object, of which a particular
    Monster type object would be composed. That is, each object would
    "have-a" object, or objects :)

    > so there is a dependency there between monster and ability, but how

    to
    > make it as weak as possible. The vector of change is definately more
    > types of abilities, and more types of monsters.


    Composition works very well at encapsulating data, which allows you to
    change dependant classes to a larger degree.

    > use case 1: monster makes a melee attack: it interrogates each of

    its
    > abilities: are you my current melee weapon, and if so, what type and
    > degree of damage do you do?


    public class BunchOfMonsters {
    public static void main (String args[]) {
    Creature blobMonster = new Monster("blob"); //"blob" is a
    monster type
    blobMonster.armWith("sword"); //sword is a type of weapon
    //have a list of monsters
    }
    }

    public class Monster implements Creature {
    public void armWith(String wep){
    if (wep == "sword") {
    Item aSword = new Sword(); } //give sword to monster
    instance
    //Sword implements Item
    }

    public void attack() {
    // find best weapon
    // find target
    }
    }


    > use case 2: monster needs to use its SPEED characetristic to

    determine
    > if it is its turn to act yet. it interogates all its current
    > abilities: here is my current SPEED - modify it if you will.


    how about each instance of Monster has an instance of Melee? Using
    Timer() each melee object determines when it gets to move. This object
    would then determine whether to fight or flee?

    > Perhaps there is a better system?


    <http://robocode.alphaworks.ibm.com/home/home.html>

    AFAIK this uses a "tick" idea, where there's a list of 'bots which gets
    iterated through once/sec; this is less complex than having a Melee
    class.


    --
    Thufir Hawat
     
    thufir, Jan 24, 2005
    #5
  6. steve mathers

    Guest

    wrote:
    > performance not an issue in this application, but codebase size is.
    > and it would be nice to be able to add new types of abilities and
    > monsters to the system just by adding a few bytes to a table and a
    > function or two to handle them, and then have a factory creatre them

    at
    > runtime.


    If each monsters attributes are composed of different objects, it
    should be very easy make a SuperSword class and have
    bigMonster.armWith("superSword") I'd think.

    I don't know how to address your codebase size concern, sorry...

    > example of the process I was thinking of:
    >
    > monster object: holds intrinsic characteristics and list of optional
    > abiltiies


    instead of a list of abilities, try for objects :)

    > ability object: enables monster to perform some function, and/or
    > modifies some of its abilities.


    As in a sword object, or fireResistant object, of which a particular
    Monster type object would be composed. That is, each object would
    "have-a" object, or objects :)

    > so there is a dependency there between monster and ability, but how

    to
    > make it as weak as possible. The vector of change is definately more
    > types of abilities, and more types of monsters.


    Composition works very well at encapsulating data, which allows you to
    change dependant classes to a larger degree.

    > use case 1: monster makes a melee attack: it interrogates each of

    its
    > abilities: are you my current melee weapon, and if so, what type and
    > degree of damage do you do?


    public class BunchOfMonsters {
    public static void main (String args[]) {
    Creature blobMonster = new Monster("blob"); //"blob" is a
    monster type
    blobMonster.armWith("sword"); //sword is a type of weapon
    //have a list of monsters
    }
    }

    public class Monster implements Creature {
    public void armWith(String wep){
    if (wep == "sword") {
    Item aSword = new Sword(); } //give sword to monster
    instance
    //Sword implements Item
    }

    public void attack() {
    // find best weapon
    // find target
    }
    }


    > use case 2: monster needs to use its SPEED characetristic to

    determine
    > if it is its turn to act yet. it interogates all its current
    > abilities: here is my current SPEED - modify it if you will.


    how about each instance of Monster has an instance of Melee? Using
    Timer() each melee object determines when it gets to move. This object
    would then determine whether to fight or flee?

    > Perhaps there is a better system?


    <http://robocode.alphaworks.ibm.com/home/home.html>

    AFAIK this uses a "tick" idea, where there's a list of 'bots which gets
    iterated through once/sec; this is less complex than having a Melee
    class.


    --
    Thufir Hawat
     
    , Jan 24, 2005
    #6
  7. steve mathers

    Chris Uppal Guest

    thufir wrote:

    > Creature blobMonster = new Monster("blob");
    > blobMonster.armWith("sword");


    Shouldn't you also have:

    blobMonster.armWith("arm");

    in there somewhere ?

    ;-)


    -- chris
     
    Chris Uppal, Jan 24, 2005
    #7
  8. steve mathers

    Chris Uppal Guest

    wrote:

    > performance not an issue in this application, but codebase size is.
    > and it would be nice to be able to add new types of abilities and
    > monsters to the system just by adding a few bytes to a table and a
    > function or two to handle them, and then have a factory creatre them at
    > runtime.


    I think you are heading in the direction of a fairly complicated and abstract
    bit of object modelling; I suggest that you take a step back and consider how
    much flexibility you actually /need/. Also I'd suggest that, whatever degree
    of flexibility you finally choose to implement, you try designing a version of
    the system (and doing a small trial implementation) /without/ considering the
    memory footprint -- you may find that you've gone up an over-abstract blind
    alley.

    It is one thing to able to mix and match different amounts of each of some
    pre-defined list of "abilities" to build new and terrible monsters. That's
    easy enough to do using classical OO. But wanting to be able to give monsters
    new /kinds/ of ability with the same ease, will require a higher level of
    abstraction; quite possibly your eventual system would look more like a
    knowledge-representation kit, or a Lisp interpreter.

    You might find that a hybrid approach would work. Most of your logic "knows"
    about hardwired abilities (speed for instance) which every monster has to some
    degree (possibly zero or even negative) and has specific code for handling
    those aspects (e.g. using strength(), currentLoad(), and currentNumberOfArms()
    to determine whether the monster can pick something up). In addition you have
    a (much) less flexible, but more data-driven extension mechanism for adding a
    little colour to your monsters. E.g. you could have Attack and Defence
    classes, where:

    class Attack
    {
    String name;
    float strength;
    int attackID;
    }

    class Defence
    {
    String name;
    float strength;
    int attackID;
    }

    and the idea is that you can add new Attack and Defence objects easily
    (representing intrinsic abilities or abilities conferred by objects/events),
    but your actual logic for dealing with them is very limited -- you just
    consider every Defence with the same attackID as each launched Attack, and
    add/subtract all the strengths before using that to change the victim's
    lifeForce(). Or you could generalise that a bit -- e.g. each Attack and
    Defence might have a defined effect on all of the victims pre-defined
    attributes (speed etc.).

    -- chris
     
    Chris Uppal, Jan 24, 2005
    #8
  9. steve mathers

    H. S. Lahman Guest

    Re: cant find a pattern to fit neatly - how to make a large numberof monsters?

    Responding to Mathers....

    > Hi , fairly new to OO design. Trying to solve a problem:
    >
    > problem:
    > I want to make a large number of different monsters. what makes
    > monsters different from each other is their 'abilities'. These could
    > such things as carrying a weapon or magic item that allows them to
    > perform an action, or something like an intrinsic resistance to attack
    > with fire, or a temporary ability ability granted by a spell cast on
    > them.
    >
    > * I want to be able to define different monster types and different
    > ability types using as little memory as possible (mobile phone
    > platform) - a hard coded table of abilities and then another table of
    > monsters that lists which ability each monster has. Some sort of
    > factory will have to create the monster given an index into this
    > table. Thats not the hard part.
    >
    > * I want to be able to add new monsters and new abilities to the table
    > without changing the inteface of the monster and ability class. I
    > think this is the hard part.
    >
    > solution: At first thought, the decorator pattern seems right, but
    > because abilities can come and go all the time, it seems to be
    > unweildy.
    >
    > I think what I want to happen is that every time the monster has to do
    > something that involves its characteristics which may be modified by
    > abilities (such as fire resistance), or it wants to perform an
    > optional action that an ability may bestow it with (such as hit
    > something with a weapon), it should interogate its entire list of
    > current abilities to see if they impact on that charicteristic or
    > action. But how to structure that process in my design?


    I don't think this is a design pattern issue; I think it is more of a
    tactical OOP optimization of a basic OOA/D. Per your first asterisk you
    have:

    [Monster]
    + type
    | *
    |
    |
    | *
    [Ability]

    which can be reified to:

    [Monster]
    + type
    | *
    |
    |
    | 1
    [AbilitySet]
    | 1
    |
    |
    | *
    [Ability]

    So each Monster has a reference to a table of its specific abilities.
    (If you need to navigate the other way, each Ability has a reference to
    a table of the Monsters with that Ability.)

    As an OOP optimization you can eliminate the collections by being clever
    about the identity of Abilities. Assuming the total number of Abilities
    is relatively limited, you can implement AbilitySet as a bitmap
    attribute of Monster where the bit position is the index into a fixed
    array of Ability references accessed by a static Ability::find(index).
    If the bit is set, the Monster has that Ability. Ability has a static
    table of its instances that is updated as the instances are created.

    The factory that creates Monsters can use external configuration data to
    obtain the bitmap value for a particular Monster type based on the
    Monster.type attribute. That can be read directly from a database. If
    the user can create custom monsters, then one can store the bitmap and
    the new type attribute for future reference.

    This pretty much limits memory to M Monsters + N Abilities + 1 static
    Ability table. The price will be performance in searching the bitmap
    and checking the Abilities to see if they are relevant.

    Note that at the cost of more bitmap attributes in Monster, one can also
    save the searching. The basic idea is to cross-reference Abilities with
    the Monster behaviors in exactly the same way:

    [Monster]
    + type
    | *
    |
    |
    | *
    [BehaviorSet]
    | 1
    |
    |
    | *
    [Ability]

    where each BehaviorSet is a list of references to the Abilities that are
    relevant to a particular Monster behavior. In effect there is a
    BehaviorSet bitmap for each behavior that Monster has. These would be
    initialized in the same way as the first case.

    The next issue is providing a generic interface to Ability. From the
    examples cited, it seems that Abilities provide rather simple parametric
    data that affects or enables certain Monster behaviors. That is,
    Ability has no intrinsic behaviors. If so, I would suggest Ability be
    in a form similar to an A-V pair. (There are many variations, such as
    XML strings.)

    Then the relevant Monster behavior can test the the attribute name to
    determine how to apply the value in its context. (The direct search via
    AbilitySet would simply ignore attributes that were not relevant to the
    behavior in hand.) Then there is only one interface needed:
    getAttribute and getValue. (Note there is nothing to prevent an Ability
    from have multiple A-V pairs; the interface just has to be slightly more
    flexible.)

    [This sort of parametric polymorphism is a sort of analysis pattern,
    BTW. I have a number of examples that might be of interest on my blog
    in the section on invariants.]

    *************
    There is nothing wrong with me that could
    not be cured by a capful of Drano.

    H. S. Lahman

    Pathfinder Solutions -- Put MDA to Work
    http://www.pathfindermda.com
    blog (under constr): http://pathfinderpeople.blogs.com/hslahman
    (888)-OOA-PATH
     
    H. S. Lahman, Jan 24, 2005
    #9
  10. steve mathers

    thufir Guest

    Chris Uppal wrote:
    > thufir wrote:
    >
    > > Creature blobMonster = new Monster("blob");
    > > blobMonster.armWith("sword");

    >
    > Shouldn't you also have:
    >
    > blobMonster.armWith("arm");
    >
    > in there somewhere ?
    >
    > ;-)
    >
    >
    > -- chris


    grrrrr ;)
     
    thufir, Jan 25, 2005
    #10
  11. steve mathers

    thufir Guest

    Here's a slightly more fleshed out idea to mull over, coming from the
    OOP paradigm :)

    I'm looking into how to make a MonsterMeleeTicker object for each
    Monster instance. MonsterMeleeTicker.setRate(3) would mean, perhaps,
    that every three seconds this monster can do one thing, be it
    fight/flee/boogie. Any pointers on what MonsterMeleeTicker should look
    like?

    All criticisms welcome, of course!

    /////////////////////code//////////////////////////
    package atreides.monsters;

    import java.util.*;

    public class TestDriveMonsters{

    private static List<Monster> list = new ArrayList<Monster>();

    public TestDriveMonsters(){
    System.out.println("TestDriveMonsters..");
    }//TestDriveMonsters

    public static void makeMonsters(){
    System.out.println("..makeMonsters");
    for (int i=0; i>5; i++){
    list.add(new Monster());
    }//for
    }//makeMonsters

    public static void main (String args[]) {
    System.out.println("..main");
    }//main
    }//TestDriveMonsters


    /////////////////////////code/////////////////////
    package atreides.monsters;

    public class Monster{

    public Monster(){}//Monster

    public static void main (String args[]) {
    System.out.println("main..");
    }//main
    }//Monster



    --
    Thufir Hawat
     
    thufir, Jan 25, 2005
    #11
  12. steve mathers

    Guest

    I see people can tell where Im coming from with this. It really helps
    to have someone else state the problem and solution in different
    language.

    Finally I think I can define the problem in a clear way:

    A monster has characteristics which are _common_ to all monsters, such
    as Speed or the ability to resist certain types of damage, even if that
    resistance is 0.
    These simple characteristics are represented as attributes in the class
    Monster.

    A monster has optional characteristics and/or behaviour which is
    represented by a list of Abilities. A sword ability, a resistance to
    fire ability of +50%, a wand of Increase Speed, etc...

    Adding new monsters is easy, you just create a monster with a different
    name, different values for its characteristics and give it a different
    starting set of abilities.

    The most important thing with this design is to make the definition of
    new abilities as easy as possible. I want a code-efficient, elegant
    way to define a new ability - the more abilities I have, the more
    different types of monsters I can easilly create. Of secondary
    importance is the impact of defining new characteristics.

    Whenever a new characteristic is defined, or a new ability defined, it
    must not change the interface between Monster and Ability. Thats a
    maintainance nightmare.

    I propose to use something like the Command Pattern between Monster and
    Ability. Monster creates a command such as 'modify this speed
    attribute', sends it to all its abilities, and those abilities may or
    may not satisfy the request.

    So when I define a new ability, I just have to define the command it
    responds to, and also the response itself. I think broadly there are
    three types of response an ability can have:

    1) modify a value passed in (i.e. yes, I modify speed, and here is your
    modified speed result)
    2) perform a function and return the result (i.e: 'yes, I am your
    currently wielded melee weapon, and I do 10 physical damage')
    3) apply an ability to a target Monster. i.e a wand of increase speed
    gives the Monster the ability to apply an 'increase speed' ability to a
    target Monster.

    so... to fully define a new type of ability, I need to define the
    strategy by which it is invoked (largely a GUI strategy issue), and/or
    the command it responds to, and the strategy it applies apon either
    being invoked or receiving that command.

    So I propose to use a type of strategy pattern to implement the
    response of an ability to a request.

    that way I can define new abilities in one table, and have a factory
    create them using the table ID.

    i.e.

    ability #5
    name: "increase speed effect"
    invoking strategy: NONE
    command: SPEED_MODFIY
    execute strategy: VALUE_MODIFIER
    execute param: +50%

    ability #6
    name: " wand of speed"
    invoking strategy: AQUIRE_TARGET
    command: NONE
    execute strategy: ADD_ABILITY
    execute param: ability #5

    and so on...
    I think its reasonable, but id be glad to hear otherwise
     
    , Jan 25, 2005
    #12
  13. steve mathers

    thufir Guest

    wrote:
    [..]
    > A monster has characteristics which are _common_ to all monsters,

    such
    > as Speed or the ability to resist certain types of damage, even if

    that
    > resistance is 0.
    > These simple characteristics are represented as attributes in the

    class
    > Monster.


    as in:
    int damageStrength = 99;

    or

    Damage strength = new Damage();

    [..]
    > So I propose to use a type of strategy pattern to implement the
    > response of an ability to a request.


    Heh, I need to check out all these patterns :)

    > that way I can define new abilities in one table, and have a factory
    > create them using the table ID.
    >
    > i.e.
    >
    > ability #5
    > name: "increase speed effect"
    > invoking strategy: NONE
    > command: SPEED_MODFIY
    > execute strategy: VALUE_MODIFIER
    > execute param: +50%

    [..]
    public class IncreaseSpeedEffect{
    boolean invokingStrategy = false;
    double executeParam = 0.50;}

    and then in, say, TestDriveMonsters:
    Monster aMonster = new Monster();
    aMonster.getInvokingStrategy();

    although I don't know what invokingStrategy does!

    FWIW, here's some java, where each monster now has a melee object. the
    same idiom can be followed to add other attributes, such as a Strategy
    class object.

    C:\>
    C:\>cd java\sources\atreides\monsters

    C:\java\sources\atreides\monsters>dir
    Volume in drive C has no label.
    Volume Serial Number is #####

    Directory of C:\java\sources\atreides\monsters

    01/25/2005 05:06p <DIR> .
    01/25/2005 05:06p <DIR> ..
    01/25/2005 05:59p 494 Monster.java
    01/25/2005 05:53p 469 MonsterTask.java
    01/24/2005 11:26p 694
    TestDriveMonsters.java
    3 File(s) 1,657 bytes
    2 Dir(s) 4,220,837,888 bytes free

    C:\java\sources\atreides\monsters>type Monster.java
    package atreides.monsters;


    public class Monster{

    java.util.Timer melee = new java.util.Timer();

    public Monster(){}//Monster

    //this method will determine how many moves a
    //monster takes. The larger the period the
    //slower the monster, the smaller the period
    //the faster. assumes positive values.

    public void setScheduleMelee(long period){
    System.out.println("..setScheduleMelee");
    MonsterTask dummyTask = new MonsterTask();
    java.util.Date nowDate = new java.util.Date();
    melee.schedule(dummyTask,nowDate,period);
    }//setScheduleMelee

    public static void main (String args[]) {
    System.out.println("main..");
    }//main
    }//Monster

    C:\java\sources\atreides\monsters>type MonsterTask.java
    package atreides.monsters;


    public class MonsterTask
    extends java.util.TimerTask
    implements java.lang.Runnable{

    public MonsterTask(){}//MonsterTask

    public boolean cancel(){
    return false;
    }//cancel

    public void run(){
    System.out.println("..run");
    }//run

    public long scheduledExecutionTime(){
    return 0;
    }//scheduledExecutionTime


    public static void main (String args[]) {
    System.out.println("main..");
    }//main
    }//MonsterTask

    C:\java\sources\atreides\monsters>type
    TestDriveMonsters.java
    package atreides.monsters;

    import java.util.*;



    public class TestDriveMonsters{

    private static List<Monster> list = new ArrayList<Monster>();

    public TestDriveMonsters(){

    System.out.println("TestDriveMonsters..");
    }//TestDriveMonsters

    public static void makeMonsters(){
    System.out.println("..makeMonsters");
    for (int i=0; i<5; i++){
    list.add(new Monster());
    }//for
    }//makeMonsters

    public static void setTimer(){
    System.out.println("..addTimer");
    for (Monster monster:list){
    }//for
    }//setTimer

    public static void main (String args[]) {
    System.out.println("..main");
    makeMonsters();
    setTimer();
    }//main
    }//TestDriveMonsters

    C:\java\sources\atreides\monsters>
     
    thufir, Jan 26, 2005
    #13
  14. steve mathers

    Lew Bloch Guest

    Re: cant find a pattern to fit neatly - how to make a large numberof monsters?

    > But how to structure that process in my design?
    > Is there a particular pattern I should be looking at?


    Interesting problem.

    Some of your space problems and complexity go away if you are willing to
    store references as object (e.g., monster) attributes. A reference is
    larger than an index, but it simplifies things tremendously.

    Allow me to essay a crude but, one hopes, illustrative object design,
    then you can pick it apart for flaws such as being too big for an
    embedded system.

    First, let me say that I won't speak to patterns as such. I am thinking
    in terms of composition and inheritance.

    I posit the following types (interfaces, ideally):

    Ability { ... }

    Weapon extends Ability { ... }

    Act
    {
    Set< Ability > abilities = new LinkedHashSet< Ability >();
    ....
    }

    Monster
    {
    Set< Ability > abilities = new LinkedHashSet< Ability >();
    ....
    }

    GameMaster
    {
    Set< Ability > allAbilities = new LinkedHashSet< Ability >();
    Set< Act > allActs = new LinkedHashSet< Act >();
    ....
    }

    Ability would be immutable, objects that report their state, such as
    speed augmentation factor, but never change it.

    At game setup, the master GameMaster object would initialize its lists
    with all available objects for the game to use. When a Monster gains,
    say, an Ability, it inserts a reference to an object from the GameMaster
    master "allAbilities" list into its private "abilities" list. The
    instance is shared by the GameMaster and by all Monsters that "have" it.

    This is relatively compact because you share instances between Monsters
    rather than have them add a
    new Ability();
    to their private lists each time.

    The tricky part is to design Ability behaviors to support actions
    performed by different Monsters. One way is to make them completely
    passive - report factors that trigger Monster behaviors. For example,
    the Monster might have

    public void attemptAct( Act act, GameThing thing )
    throws GameException
    {
    /* load required factors, e.g., speed, from Monster */
    act.loadBaseFactors( this );

    for( Ability a : act.getAbilities() )
    {
    if ( act.requires( a ) && ! abilities.contains( a ) )
    {
    return;
    }
    act.modifyFactors( a ); // apply mods from the ability
    }

    act.execute( thing ); // throws GameException
    }

    The Act object, "act", has to know how to perform its deed upon the
    passed "thing" - e.g., how to attack a Monster (subclass of GameThing).
    First it loads its attack factor (in this case) from the Monster's
    base attributes like strength. Then it examines each used Ability for
    how it affects those factors. The attack Act should know to add one to
    "strength" upon seeing a strengthPotion Ability, or subtract one for a
    fever Ability.

    After the Ability modification loop, the Act tries to do its thing
    (attack) to its GameThing target (other Monster), using its modified
    (attack) factors. (It can likewise scoop Abilitys from the target to
    calculate defensive capability.)

    This is a crude sketch, and optimizations suggest themselves almost
    immediately. The main point is that Ability objects are passive, so
    they can be shared and thus save memory.

    Actually, complete passiveness is not required, only immutability. The
    Ability class can define reentrant methods - no changes to the Ability's
    members, only to method parameters and stack variables.

    Incidentally, the Act object can be reused as each Monster gets its turn
    to try it. This also saves memory.

    I don't know J2ME so if java.util.LinkedHashSet isn't available use any
    java.util.Set, or failing that, roll your own with similar characteristics.
     
    Lew Bloch, Feb 3, 2005
    #14
  15. steve mathers

    Thufir Hawat Guest

    Lew Bloch wrote:
    [..]
    > Actually, complete passiveness is not required, only immutability.

    The
    > Ability class can define reentrant methods - no changes to the

    Ability's
    > members, only to method parameters and stack variables.
    >
    > Incidentally, the Act object can be reused as each Monster gets its

    turn
    > to try it. This also saves memory.
    >
    > I don't know J2ME so if java.util.LinkedHashSet isn't available use

    any
    > java.util.Set, or failing that, roll your own with similar

    characteristics.

    Why did you select LinkedHashSet over LinkedHashMap? That's not really
    my question, though. I'm more interested in the use of "Hash" in a
    collection. A Hash is a sort of unique id for each instance? I
    believe it to be related to the toString() default method in that
    hashCode() is so similar:

    public int hashCode()
    Returns a hash code value for this enumeration value. The hash code
    is just this enumeration value's integer value.


    public String toString()
    Returns a string value corresponding to this enumeration value.




    "A map cannot contain duplicate keys"
    <http://java.sun.com/docs/books/tutorial/collections/interfaces/index.html>

    That sounds like a Set, to me. Whether one is preferable (in J2ME or
    J2SE) over the other might be contentious (?), their common quality of
    "Hashness" is new and interesting to me...



    --
    Thufir Hawat
     
    Thufir Hawat, Feb 3, 2005
    #15
  16. One solution to this problems :

    -Use the MetaCalss design pattern (MonsterKind is an abstract class, an
    instance of Monster have exactly one MonsterKing - MonterKing is a kind of
    singleton for the race, and each Monster is associated with its arm)

    -Use the strategy design pattern to associate a "way to calculate damages"
    to a weapon.

    Search the web for inforations about these patterns :)

    Regards,
    Lucien.
     
    Utilisateur PC Libre Service, Feb 3, 2005
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. steve mathers
    Replies:
    0
    Views:
    312
    steve mathers
    Jan 23, 2005
  2. Piet
    Replies:
    0
    Views:
    549
  3. Nagaraj
    Replies:
    1
    Views:
    872
    Lionel B
    Mar 1, 2007
  4. Ben Galyean

    Where did the monsters go?

    Ben Galyean, Apr 22, 2008, in forum: Ruby
    Replies:
    7
    Views:
    131
    Phlip
    Apr 23, 2008
  5. Geoff Soper
    Replies:
    2
    Views:
    149
    Lasse Reichstein Nielsen
    Jan 26, 2004
Loading...

Share This Page