001package agent.four;
002
003public class Main {
004        public static void main (String[] args) {
005                World w = WorldF.instance(100,100);
006                int i = 0;
007                while (i<20) {
008                        try {
009                                new Tiger
010                                (Integer.toString(i), Util.random(w.maxx()), Util.random(w.maxy()));
011                                i++;
012                        } catch (SpaceOccupiedException e) {
013                        }
014                }
015                w.run(1000);
016        }
017}
018
019class Util {
020        private Util() {}
021        private final static long SEED = 2497;
022        private final static java.util.Random r = new java.util.Random(SEED);
023        static int random(int n) { return r.nextInt(n); }
024        static boolean randomBoolean() { return r.nextBoolean(); }
025}
026
027interface World extends TimeServer {
028        public int maxx();
029        public int maxy();
030        public Visible get(int i, int j);
031        public boolean set(int i, int j, Visible a);
032}
033
034class WorldF {
035        private static World W;
036        public static World instance(int maxx, int maxy) {
037                if (W != null)
038                        throw new IllegalStateException();
039                W = new WorldObj(maxx, maxy);
040                return W;
041        }
042        public static World instance() {
043                if (W == null)
044                        throw new IllegalStateException();
045                return W;
046        }
047}
048
049class WorldObj implements World {
050        private final int maxx;
051        private final int maxy;
052        private final TimeServer time;
053        private final Visible[][] space;
054
055        WorldObj(int maxx, int maxy) {
056                this.maxx = maxx;
057                this.maxy = maxy;
058                time = new TimeServerLinked();
059                space = new Visible[maxx][maxy];
060                for (int x = 0; x < maxx; x++ )
061                        for (int y = 0; y < maxy; y++ )
062                                space[x][y] = NullVisible.instance;
063        }
064        public int maxx() { return maxx; }
065        public int maxy() { return maxy; }
066        public Visible get(int x, int y) {
067                return space[(x+maxx)%maxx][(y+maxy)%maxy];
068        }
069        public boolean set(int x, int y, Visible a){
070                if (a == null) {
071                        a = NullVisible.instance;
072                } else if (get(x,y) != NullVisible.instance) {
073                        return false;
074                }
075                space[(x+maxx)%maxx][(y+maxy)%maxy] = a;
076                return true;
077        }
078        public long currentTime()              { return time.currentTime(); }
079        public void enqueue(long t, Agent a)   { time.enqueue(t,a); }
080        public void run(int d)                 { time.run(d); }
081}
082
083interface Visible {
084        public final static int NULL = 0;
085        public final static int TIGER = 1;
086        public int type();
087}
088
089class NullVisible implements Visible {
090        private NullVisible() {}
091        public final static Visible instance = new NullVisible();
092        public int type() { return Visible.NULL; }
093        public String toString() { return "Null"; }
094}
095
096class SpaceOccupiedException extends RuntimeException {
097        private static final long serialVersionUID = 2008L;
098};
099
100class Tiger implements Agent, Visible {
101        private String name;
102        private int x;
103        private int y;
104        private World w = WorldF.instance();
105
106        public Tiger(String name, int x, int y)
107                        throws SpaceOccupiedException
108        {
109                this.name = name;
110                if (!w.set(x,y,this))
111                        throw new SpaceOccupiedException();
112                this.x = x;
113                this.y = y;
114                w.enqueue(1+w.currentTime(), this);
115        }
116
117        public String toString() { return name + "@(" + x + "," + y + ")"; }
118
119        public int type() { return Visible.TIGER; }
120        public void check() {
121                checkAjacent();
122        }
123        public void run() {
124                //System.out.print(this + " moves to ");
125                moveRandom();
126                //System.out.println(this);
127                w.enqueue(10+w.currentTime(), this);
128        }
129
130        private void checkAjacent() {
131                for (int i=-1; i<=1; i++) {
132                        for (int j=-1; j<=1; j++) {
133                                if (i==0 && j==0)
134                                        continue;
135                                if (w.get(x+i,y+j).type() == Visible.TIGER)
136                                        System.out.println(this + " roars at " + w.get(x+i,y+j) + " at " + w.currentTime());
137                        }
138                }
139        }
140        private void moveRandom() {
141                w.set(x,y,null);
142                int xNew, yNew;
143                do {
144                        xNew = (w.maxx() + this.x -1 + Util.random(2)) % w.maxx();
145                        yNew = (w.maxy() + this.y -1 + Util.random(2)) % w.maxy();
146                        //System.out.println("Trying (" + x + "," + y + ")");
147                } while (!w.set(xNew,yNew,this));
148                this.x = xNew; this.y = yNew;
149        }
150}