import java.awt.*; import java.awt.event.*; import java.awt.Graphics; import javax.swing.*; import java.rmi.*; import java.rmi.server.*; class hrdisplay extends JFrame // graphics class { public int FRAMEDELAY = 50; private Graphics brush; public Graphics display; private Image canvas; // off-screen graphics buffer private Image background; // racing background gif private Image staticbkgrd; // static (stretched) background; private Image racergif; // horse and rider animated gif public int HN = 3; // number of horses public int TW = 800; // track length; public int TH; // track height - depends on number of racers public int LW = 60; // lane width public byte id; // my id in the race public horse[] H; // information for all horses public dhrclient mydhr; // pointer to dhr synchronization manager public void paint(Graphics g) {} // overrides auto-update public void init(String[] args) { try { TH = (this.HN * this.LW) + this.LW+10; setBounds(0,0,TW,TH); setVisible(true); background = Toolkit.getDefaultToolkit().getImage("hrbackground.gif"); prepareImage(background,this); racergif = Toolkit.getDefaultToolkit().getImage("racer.gif"); prepareImage(racergif,this); canvas = createImage(TW,TH); staticbkgrd = createImage(TW,TH); brush = canvas.getGraphics(); // to double buffer brush.setColor(Color.blue); display = this.getGraphics(); // to screen try { Thread.sleep(750); } catch (InterruptedException IE) {} staticbkgrd.getGraphics().drawImage(background,0,0,TW,TH-30,null); resetbackground(); displayStatus("waiting for other racers ..."); display.drawImage(canvas,0,0,null); // draws to screen race(); } catch (Exception e) {System.out.println(e);} } // init public int randint(int min, int max) { return (int) (Math.random() * (max-min+1) + min); } private void resetbackground() { brush.drawImage(staticbkgrd,0,30,null); // draw track lines brush.setColor(Color.blue); for(int i=1;i<=HN+1;i++) { brush.drawLine(0,(i*LW)-5,TW-1,(i*LW)-5); } // finish line: brush.setColor(Color.red); brush.drawLine(TW-15,0,TW-15,TH-1); // finish line } // resetbackground public void nextframe(int delay) // delay in ms { try { Thread.sleep(delay); } catch (InterruptedException IE) {} display.drawImage(canvas,0,0,null); // draws to screen resetbackground(); } // nextframe with ms delay public void displayStatus(String message) { Font oldfont = brush.getFont(); brush.setFont(new Font("Serif",Font.BOLD,24)); brush.drawString(message,TW/3,LW-10); brush.setFont(oldfont); } public void draw(horse racer) { if (racer==null || (!racer.inrace)) return; brush.setColor(Color.black); brush.drawString(racer.name,10,(racer.y+55)); brush.drawImage(racergif,racer.x,racer.y,null); } boolean stoprace = false; public void race() throws Exception { int i; // loop counter stoprace = false; int winner; for(i=0;i lead) { lead = H[i].x; winner = i; } else if (H[i].x == lead) winner = -1; if (H[i].x > TW-68) stoprace = true; // stops race } // for loop return winner; } // determineLeader } // class hrdisplay ////////////////////////////////////////////////////////////////////// public class dhrclient extends UnicastRemoteObject implements dhr { long localseq = 0; hrdisplay localrace; dhr neighbor; boolean initialization = true; static raceinfo localinfo; public dhrclient() throws RemoteException {} //called remotely: public synchronized void passpermit(raceinfo ri) throws RemoteException { localseq = ri.seq; if (ri.horses[localrace.id] == null) ri.horses[localrace.id] = localrace.H[localrace.id]; // join race localrace.H = ri.horses; // update info //System.out.println("passpermit call accepted, notifying..."); notify(); } public synchronized void block() throws Exception { localinfo.horses = localrace.H; localinfo.seq += 1; //System.out.println("preparing to call passpermit from block()"); if (localrace.id!=0) initialization = false; if (!initialization || localrace.id==0) { neighbor.passpermit(localinfo); //System.out.println("after passpermit returned; from block()"); } wait(); } // args[0] is name of horse, args[1] is number of racers, // args[2] horse id, args[3] is neighbor ip, and args[4] is self ip // and args[5] is delaytime (not so critical this time) public static void main(String[] args) throws Exception { System.setProperty("java.security.policy", "server.policy"); System.setSecurityManager( new RMISecurityManager()); hrdisplay session = new hrdisplay(); if (args.length>5) session.FRAMEDELAY = Integer.parseInt(args[5]); session.HN = Integer.parseInt(args[1]); // number of horses in race session.H = new horse[session.HN]; // create empty array session.id = (byte)Integer.parseInt(args[2]); // make local horse object session.H[session.id] = new horse(true,0,(session.id*session.LW)+session.LW,args[0]); dhrclient me = new dhrclient(); me.localrace = session; session.mydhr = me; me.localinfo = new raceinfo(session.H); // bind me to local registry: Naming.rebind("//"+args[4]+"/dhracer",me); // change to your real ip // lookup neighbor racer // loop needed because initially nobody's bound: boolean tryagain = true; System.out.println("finding neighbor ..."); while (tryagain || me.neighbor==null) { try { me.neighbor = (dhr)Naming.lookup("//"+args[3]+"/dhracer"); tryagain = false; } catch (Exception ie) { tryagain = true;} } session.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {System.exit(0);} }); System.out.println("initializing race"); session.init(args); Naming.unbind("//127.0.0.1/dhracer"); // invalidate bind } // main } // dhrclient