Hoijui already knows some of these, but I thought it would make sense to document them a bit better, and offer others the chance to give input too.
Also I'd like to say that having this interface available is really epic win, good job hoijui

So here are my comments:
Unit testing - 1
Unit testing anything significant in a Java AI is currently not possible*, because the com.springrts.ai.oo classes can not be instantiated outside the AIInterface package. Even if they could be instantiated, they couldn't be used because they depend on a running instance of Spring.
*unless I make boring proxy classes for everything in com.springrts.ai.oo
My request is to generate for all classes not only the class, but also a public interface, to allow creation of mock objects, which in turn allows unit testing.
For example, what is now the Unit class, would become an UnitImpl class that implements a public Unit interface. All public functions would refer to the interface only, instead of referring explicitly to UnitImpl. (I assume internally only getUnitId()/getUnitDefId()/etc. are needed.)
Unit testing - 2
With the above in place at least unit testing is possible, but one still needs to make mock objects. Since I think these mock objects would be nearly identical for everyone who wants them, and it should be relatively easy to generate those, they should be included IMO.
They could just consist of a field and a getter/setter for every get* method in the respective interface.
E.g.
Code: Select all
package com.springrts.ai.test;
import com.springrts.ai.oo.Unit;
public class MockUnit implements Unit {
private float[] pos;
public void setPos(float[] pos) {
this.pos = pos;
}
@Override
public float[] getPos() {
return pos;
}
// etc.
}
OOAIFactory access problems
Now I was trying to get rid of duplication because of the different but quite similar events, since I've lots of forwarding/filtering of events in the design I have in mind. (based on C.R.A.I.G.)
- unitCreated
- unitFinished
- unitDamaged
- enemyEnteredLOS
- enemyLeftLOS
- etc.
Code: Select all
interface {
void gameEvent(AIEvent event);
}
Suggested fix: Make OOAIFactory.ais and OOAIFactory.ooClbs protected, or offer public or protected accessors that return (readonly views of) these maps.
Then, I tried to just copy the OOAIFactory class (as this implements AI, just like NullJavaAI), but this didn't work because OOAICallback.getInstance is not visible outside the AI interface package. So it seems I do not have access to all the OOAICallback functionality unless I use OOAIFactory...
Suggested fix: make OOAICallback.getInstance public, or offer some other way to get/create an instance of this class.
EDIT: hmm, this applies to Unit.getInstance too. So AFAICS it's currently impossible to reuse the event classes in any way, I can only copy/reimplement them all, and then instantiate them in the OOAI.unitCreated/unitFinished etc. methods. (Resulting in a chain of conversions: event class based->method based->event class based.)
AIEvents
This is a bit more controversial suggestion; maybe it's too specific to my AI ideas.
I've noticed the fields of this class are just public and there are no getters. Also I've noticed this is a quite flat inheritance hierarchy and it's without any interfaces. Many of the events are quite similar however.
Hence, for reasons mentioned above, I would like it if similar events would implement the same interface. E.g. all Unit*AIEvent would implement the interface UnitAIEvent { Unit getUnit(); }, all Enemy*AIEvent would implement the interface EnemyAIEvent { Unit getEnemy(); }, etc. Note also the similarity between EnemyDamaged and UnitDamaged, and UnitGiven and UnitCaptured.
Having such common interfaces available would really ease filtering events when one implements them as I mentioned above.
For example, I could then just do something like:
Code: Select all
unitSpecificEvents.get(unitEvent.getUnit()).gameEvent(event);
(In Lua this was really easy due to the dynamic nature of the language
