maybe I should avoid multiple inheritance where possible, and use java's interface style, inheriting things like "useable", "kickable", etc. try doing an example with a -very- simple world object, and three object types, wolves, deer, and plants. plant rots with time meat rots with time grass is a plant grass grows at a fixed rate herbivores eat plants carnivores eat meat animals are meat animals breed at a rate relative their number animals get stronger when they eat more animals die when they get too weak animals pregnancies abort then they get too weak deer are animals deer are herbivores wolves are animals wolves are carnivores Object: abstract? Physical Object: mass - how heavy an object is, in grams volume - how big an object is, in mL x,y - location coordinates sector - specifies sector object is in Eatable: can be eaten Cookable: can be cooked cooked - how cooked it is Alive: an object that is alive Meat: eatable, cookable rots with time may give diseases when not cooked Plant: eatable(inherant), cookable(irrelivant for now), alive rots with time alive - how alive it is (goes down when not watered, etc) Grass: plant How is the "world" done? Sectors: areas of locality all queries about surrounding areas originate from current sector x[],y[] - set of boundary polygon vertices sector[] - set of adjoining sectors, index coresponding to edge after same vertex object[] - list of objects in the sector Philotic binding: how did my philotic binding idea work? any interaction of any type must be accompanied by some kind of philotic bind. an object is philoticly bound to objects near it by nearness philotes. * /| / | / |h1 / | / o1 | *-----+ w1 tan(o1) = h1/w1 o1 = arctan(h1/w1) ************************************************** Constructors for ALL objects: Since some properties specified by inherited types may need to be overridden (say, a super-wolf that doesn't age. "ages" is specified by inherited "carnivore"), a special constructor is needed. Takes some special class to specify constructor, and sets an internal variable to nullify the actions of all methods. For example: class Ages { public: Ages(NullAndVoid __x) { unused = true; } void setUnused(bool _unused) { unused = _unused; } bool getUnused() { return unused; } void tick() { if (!unused) { /* ... */ } } private: bool unused; }; ************************************************** carnivore: mustEat, ages, alive, meat, sexual canEat: can eat only meat. herbivore: mustEat, ages, alive, meat, sexual canEat: can eat only plants. plant: alive, eatable, rots, asexual for now, let's assume plants reproduce by budding. needs water. tick: only tick rots when not alive. meat: eatable, rots water: drinkable river: water never --water pond: water sexual: reproduces asexual: reproduces Interactions: actor: the object performing the action. action: the action the actor is performing on the target. target: the object the action is being performed on. condition: if the condition is met, the reaction is performed(queued?). reaction: the action that is performed(queued?) when the condition is met. actor action target condition reaction --------------------------------------------------------------------------------------------------- carnivore sees drinkable actor->thirsty && dist(actor,target)thirsty move toward target carnivore sees !alive && meat actor->hungry && actor->canEat(target) && dist(actor,target)hungry && actor->canEat(target) move toward target carnivore sees alive && meat actor->hungry && actor->canEat(target) && dist(actor,target)hungry && actor->canEat(target) move toward target carnivore eats meat !target->rotten && actor->canEat(target) --hunger carnivore attacked(by) * actor->health>x attack target carnivore attacked(by) * actor->health<=x && can move away move away from target carnivore attacked(by) * * attack target --------------------------------------------------------------------------------------------------- herbivore sees drinkable actor->thirsty && dist(actor,target)thirsty move toward target herbivore sees carnivore dist(actor,target)canEat(actor) move away from target herbivore sees plant actor->hungry && actor->canEat(target) move toward target herbivore sees plant actor->hungry && actor->canEat(target) && dist(actor,target)rotten && actor->canEat(target) --hunger herbivore attacked(by) * can move away move away from target herbivore attacked(by) * * attack target --------------------------------------------------------------------------------------------------- water touches plant * water target water touches dirt dirt->porus water target water waters * * --mass --volume --------------------------------------------------------------------------------------------------- plant watered(by) water * ++water plant tick n/a actor->waterwater>y --health plant tick n/a actor->alive ++health plant tick n/a !actor->alive && !actor->Rots::unused actor->Rots::setUnused(true) --------------------------------------------------------------------------------------------------- dirt touches plant target->waterwaterhunger<=x ++hunger mustEat tick n/a actor->hunger>x ++hunger --health ages tick n/a actor->age<=x ++age ages tick n/a actor->age>x ++age --health actor->perform(Action action, Object target) all public methods of target are available. all methods of actor are available. action is a simple type. preferable, the target's type should be identified, and the action and target dispatched to a method if type actionName(Action action, SpecificObject target) As action may contain additional information about the action, such as strength, it should be passed to the submethod. after an action has been resolved, the reverse should be performed, probably by the action dispatcher. target->performReverse(Action action, Object actor) /********** (too overkill) target->perform(ReverseAction action, Object actor) as shown, there should be two -different- functions for perform(...), one that takes an Action and an Object, and one that takes a ReverseAction and an Object, where Action and ReverseAction are distinct base types, with no object that inherits -both-. ***********/ eg. wolf sees deer, and is hungry, queues move action. deer seen by wolf. no reaction eg. wolf attacks deer, queues another attack action. deer attacked by wolf, queues a move action. for now, assume no line of sight. can see anything within specific radius. bound world with rock. cannot pass beyond. impassable barrier. no gravity model, flat world. when it rains, ponds are simply ++watered, rivers are untouched. rivers assumed to be shallow enough to cross at all points. model dirt as large 3d set (not array) of cubical dirt "chunks". How can I write the OE in Java? I have to avoid multiple inheritance somehow. What if, I use a parent.handle(...) concept? use a properties object, to store all an objects properties. AnimalHandler() CarnivoreHandler() pass actions to the appropriate handler doAction(action, ...) { case action ...: ah = new AnimalHandler(this) ah.perform(action, ...); ...: ch = new CarnivoreHandler(this) ch.perform(action, ...); } perform(action, ...) { dostuff } ------------------------------------------------------------------------ Ideas from discussing with Ben on the PG trip Behavior objects objects' behaviors are defined in a seperate behavior object behavior objects contain vectors of actionHandlers actionHandlers are queried about handling an action whenever an action is performed on an object