APPENDIX C

MARBLES WORLD SERVER CODE

import java.net.*;

import java.io.*;

import java.util.Date;

import dtai.net.*;

 

public class Connector extends NetServer

{

    ConnectToClient c[]={null,null,null,null};

    int connects=0;

    int mode2=0;

    int mode3=0;

    int pieces = 0;

    int maxpieces = 10;

    int effects = 0;

    int maxeffects = 0;

    int goalx[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    int goaly[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    int roundno=100;  //Keep track of questions and time reports

    int count=0;    //Keep track of reports in

    long time[] = {0,0,0,0};   //time for last round

    long report[] = {0,0,0,0};   //reporting time

    int speed[] = {-9,-9,-9,-9};   //current speed

    long maxturntime;

    Date theDate;

    long starttime;

    String details = "";

    String sim_type = "0";

    int slowest=0;

       

    public static void main ( String argv[] ) {

             

                        try {

                                        int port = 8765;

                                        new Connector( port,argv[0] );

                        }

                        catch ( Exception e ) {

                                        e.printStackTrace();

                        }

          }

 

          public Connector( int portnum, String st ) {

                        super ( portnum );

        createGoals(10);

        sim_type = st;

        if (sim_type.charAt(0)=='0') {roundno=103;}

          }



 

          public void createClientPort( Socket socket )

          {

                        try {

                            if(connects <4) {

                addClient(new ConnectToClient ( this, socket ));

                speed[connects]=-1;

                c[connects++].start();

                writeToAll("0" + connects + "" + sim_type); //update player count & simulation_type

                                System.out.println("0" + connects + "" + sim_type);

            }   

                        }

                        catch( IOException ioe ) {

                                        ioe.printStackTrace();

                        }

          }

         

    public void addClient(ConnectToClient ctc) {

        if (connects<4) c[connects] = ctc;

                        System.out.println(connects);

    }

   

    public void writeToAll(String s) {

                        try {

            for(int x=0;x<connects;x++) {

                c[x].writeUTF(s);

                c[x].flush();

            }

        }   

        catch( IOException ioe ) {

                                        ioe.printStackTrace();

                        }

    }

   

    public void writeToOne(String s,int n) {

                        try {

            c[n].writeUTF(s);

            c[n].flush();

        }   

        catch( IOException ioe ) {

                                        ioe.printStackTrace();

                        }

    }

 

    public void writeDetails(String s,int m) {

                        try {

                           if(m==0) {

               DataOutput s_out = new DataOutputStream(new FileOutputStream("worldo.txt"));

               s_out.writeUTF(s);

           } else {

               DataOutput s_out2 = new DataOutputStream(new FileOutputStream("score.txt"));

               s_out2.writeUTF(s);

           }

        }

        catch( IOException ioe ) {

                                        ioe.printStackTrace();

                        }

    }

 

    public void readDetails(int who) {

        String line;

                        try {

           DataInput s_in = new DataInputStream(new FileInputStream("worldi.txt"));

           line = s_in.readLine();

           writeToOne("1103109" + line,who);

           line = s_in.readLine();

           writeToOne("1109112" + line,who);

           line = s_in.readLine();

           writeToOne("1112113" + line,who);

           line = s_in.readLine();

           writeToOne("1113114" + line,who);

           line = s_in.readLine();

           writeToOne("1114115" + line,who);

           line = s_in.readLine();

           writeToOne("1115116" + line,who);

           line = s_in.readLine();

           writeToOne("1116117" + line,who);

           line = s_in.readLine();

           writeToOne("1117200" + line,who);

           line = s_in.readLine();  //read the w

           line = s_in.readLine();  //read first goal

           while(line.charAt(0)!='y') {

               writeToOne(line,who);

               line = s_in.readLine();

           }

           line = s_in.readLine();  //read first obstacle

           while(line.charAt(0)!='x') {

               writeToOne(line,who);

               line = s_in.readLine();

           }

        }

        catch( IOException ioe ) {

                                        ioe.printStackTrace();

                        }

    }

   

    public void checkMode2 () {

        if (mode2==connects) {

                            writeToAll("92");

                        }   

          }           

 

    public void checkMode3 () {

        if (mode3==connects) {

                            writeToAll("93");

            writeDetails(details,0);

                        }   

          }           

           

    public void recalcSpeeds() {

        long value=0;

        long value1=0;

        int catchup[]={0,0,0,0};  //additional added/subtracted to catchup for reporting lags

       

        if(connects<2) {return;} // no need to recalc speed if just one participant

        if(roundno==100) {

            slowest=0;

            for(int x=1;x<connects;x++){

                if(time[x]>time[slowest]) {

                    slowest=x;

                }   

            }   

            for(int x=0;x<connects;x++){

                if(x==slowest) {

                    speed[x]=20;

                } else {

                    speed[x]=(int)(20+((time[slowest]-time[x])/30)); //base initial speed relative to slowest

                }

                writeToOne("8" + speed[x],x);

                System.out.println("speed " + x + " " + speed[x]);

            }   

        } else {  //not the initial speed set, use performance to base

          for(int x=0;x<connects;x++){  //recalculate speed for next 50 frames for each participant

            time[x]=time[x]-(catchup[x]*50); //find true time discounting any additions for catch up

            if((time[x]-time[slowest])>0 && (report[x]-report[slowest])>0) { //running too slow

                speed[x]=(int)(speed[x]+(time[slowest]-time[x])/200); //adjust for a quarter of the difference

                catchup[x]=(int)((report[slowest]-report[x])/50);

                writeToOne("8" + (speed[x]+catchup[x]),x);

            } else if ((time[x]-time[slowest])<0 && (report[x]-report[slowest])<0) { //running too fast

                speed[x]=(int)(speed[x]+(time[slowest]-time[x])/200); //adjust for a quarter of the difference

                catchup[x]=(int)((report[slowest]-report[x])/50);

                writeToOne("8" + (speed[x]+catchup[x]),x); //send catch up correcter without updating speed variable

            } else {

                catchup[x]=0;

            }   

            System.out.println("speed " + x + " " + (speed[x]+catchup[x]) + " time " + time[x] + " report " + report[x]);

          }   

        } 

    }

 

    public void createGoals(int n) {

       boolean valid;  

 

       for(int x=0;x<n;x++) {

          valid=false;

          while(!valid) {

             goalx[x] = (int)(Math.random()*1000);

             goaly[x] = (int)(Math.random()*1000);

               valid=true;

               double p = goalx[x] - 100; //i.mw.anim.ball[0]

               double q = goaly[x] - 500;

               double h2 = p*p + q*q;

               double h = Math.sqrt(h2);

               if (h < 50) { // too close

                       valid = false;

               } else {

                   p = goalx[x] - 900;

                   q = goaly[x] - 500;

                   h2 = p*p + q*q;

                   h = Math.sqrt(h2);

                   if (h < 50) { // too close

                           valid = false;

                   } else {

                       p = goalx[x] - 500;

                       q = goaly[x] - 100;

                       h2 = p*p + q*q;

                       h = Math.sqrt(h2);

                       if (h < 50) { // too close

                               valid = false;

                       } else {

                           p = goalx[x] - 500;

                           q = goaly[x] - 900;

                           h2 = p*p + q*q;

                           h = Math.sqrt(h2);

                           if (h < 50) { // too close

                                   valid = false;

                           }

                       }

                   }

               }

           }

       }

    }

}

 

class ConnectToClient extends NetPortToClient {

    Connector conn;

    int qno=103;  //Question Number

    int pno=-1;   //Player Number

    int value=0;

    long value1=0;

    int value2=0;

       

          public ConnectToClient(Connector server, Socket socket) throws IOException {

                        super( server, socket );

                        conn=server;

          }

 

          protected void readInput() throws IOException {

                        String command = readUTF();

              if(command.charAt(0)=='1') {

               qno=Integer.parseInt("" + command.charAt(1)+ command.charAt(2)+

                   command.charAt(3));

               pno=Integer.parseInt("" + command.charAt(4));

               value=Integer.parseInt("" + command.substring(5));

               if(qno==103) {

                    conn.speed[pno-1]=value;

                    if(conn.speed[0]!=-1&&conn.speed[1]!=-1&&conn.speed[2]!=-1&&conn.speed[3]!=-1) {

                        value=0;

                        for(int x=0;x<conn.connects;x++) {

                            value=value+conn.speed[x];

                            conn.speed[x]=-1;

                        }

                        value=(int)(value/conn.connects);

                        if (value<1) {conn.maxturntime=5000;}

                        else if (value<2) {conn.maxturntime=10000;}

                        else if (value<3) {conn.maxturntime=15000;}

                        else if (value<4) {conn.maxturntime=20000;}

                        else if (value<5) {conn.maxturntime=25000;}

                        else if (value<6) {conn.maxturntime=30000;}

                        else if (value<7) {conn.maxturntime=45000;}

                        else if (value<8) {conn.maxturntime=60000;}

                        else {conn.maxturntime=120000;}

                        System.out.println("Max Time " + conn.maxturntime);

                        value2=109;

                        conn.writeToAll("1" + qno + "" + value2 + "" + value);

                        conn.details = "" + value + "\n";

                        conn.theDate = new Date();

                        conn.starttime = conn.theDate.getTime();

                    }   

               } else if(qno==104) {

                    conn.maxpieces=value+1;

                    value2=qno+1;

               } else if(qno==105) {

                    conn.maxeffects=value+1;

                    value2=qno+1;

               } else if(qno==109) {

                    conn.theDate = new Date();

                    System.out.println("Against Time " + conn.theDate.getTime() + " Start " + conn.starttime);

                    if((conn.theDate.getTime()-conn.starttime)>conn.maxturntime){

                        for(int x=0;x<conn.connects;x++) {

                            if(conn.speed[x]==-1) {conn.speed[x]=-9;}

                        }

                    } else {   

                        conn.speed[pno-1]=value;

                    }   

                    if(conn.speed[0]!=-1&&conn.speed[1]!=-1&&conn.speed[2]!=-1&&conn.speed[3]!=-1){

                        value=0;

                        conn.roundno=0;

                        for(int x=0;x<conn.connects;x++) {

                            if(conn.speed[x]!=-9) {

                                value=value+conn.speed[x];

                                conn.roundno++;

                            }   

                            conn.speed[x]=-1;

                        }

                        if (conn.roundno==0) {value=4;}

                        else {

                           value=(int)(value/conn.roundno);

                        }  

                        value2=112;

                        conn.writeToAll("1" + qno + "" + value2 + "" + value);

                        conn.details = conn.details + value + "\n";

                        conn.theDate = new Date();

                        conn.starttime = conn.theDate.getTime();

                    }   

               } else if(qno==200) {

                    conn.pieces++;

                    if(conn.pieces<conn.maxpieces) {

                        value2=200;

                    } else {

                        conn.pieces=0;

                        conn.maxpieces=40;

                        value2=qno+1;

                    }

               } else if(qno==201) {

                    conn.effects++;

                    if(conn.effects<conn.maxeffects) {

                        value2=201;

                    } else {

                        conn.effects=0;

                        value2=999;

                    }

               } else {

                    conn.theDate = new Date();

                    if((conn.starttime+conn.maxturntime)>conn.theDate.getTime()){

                        for(int x=0;x<conn.connects;x++) {

                            if(conn.speed[x]==-1) {conn.speed[x]=-9;}

                        }

                    } else {   

                        conn.speed[pno-1]=value;

                    }   

                    if(conn.speed[0]!=-1&&conn.speed[1]!=-1&&conn.speed[2]!=-1&&conn.speed[3]!=-1){

                        value=0;

                        conn.roundno=0;

                        for(int x=0;x<conn.connects;x++) {

                            if(conn.speed[x]!=-9) {

                                value=value+conn.speed[x];

                                conn.roundno++;

                            }   

                            conn.speed[x]=-1;

                        }

                        if (conn.roundno==0) {value=4;}

                        else {

                            value=(int)(value/conn.roundno);

                        }  

                        value2=qno+1;

                        if(qno==117) {

                            conn.roundno=100;

                            for(int x=0;x<conn.connects;x++) {

                                conn.speed[x]=0;

                            }   

                            value2=999;

                        }

                        conn.writeToAll("1" + qno + "" + value2 + "" + value);

                        conn.details = conn.details + value + "\n";

                        if(qno==117) {

                            conn.details = conn.details + "w" + "\n";

                        }   

                        conn.theDate = new Date();

                        conn.starttime = conn.theDate.getTime();

                    }   

               }

               conn.writeToAll("1" + qno + "" + value2 + "" + value);

        }

                        else if(command.charAt(0)=='4') {

                               conn.pieces++;

                               value=Integer.parseInt("" + command.charAt(1));

                               value++;

                               if(value>conn.connects) {value=1;} //update whose turn it is

                               command = command.charAt(0) + "" + value + command.substring(2);

               conn.writeToAll(command);

               conn.details = conn.details + command + "\n";

               if(conn.pieces>=conn.maxpieces) {

                  conn.details = conn.details + "x\n";

                  conn.writeToAll("92");

               }

               System.out.println(command);

                        }   

              else if(command.charAt(0)=='6') {  //load goals (and other objects)

                      value=Integer.parseInt("" + command.charAt(1))-1;

                if(conn.sim_type.charAt(0)=='1') {

                    conn.readDetails(value);

                } else {

                   for(int x=0;x<10;x++) {

                      command="6"+(1000+conn.goalx[x])+(1000+conn.goaly[x]);

                      conn.writeToOne(command,value);

                      System.out.println(command);

                      if(value==0) { conn.details = conn.details + command + "\n"; }

                   }

                if(value==0) {conn.details = conn.details + "y" + "\n";}

                }

        }

              else if(command.charAt(0)=='8') { //reading a time report

            System.out.println(command);

            value2=Integer.parseInt("" + command.charAt(1)); //player number

            value=Integer.parseInt("" + command.charAt(2)+ command.charAt(3)+

                                         command.charAt(4)); //round number

            value1=Long.parseLong("" + command.substring(5)); //time for round

                  if(value==100) { //send initial time estimate

                 System.out.println("initial speed: " + value1);

                 conn.time[value2-1]=value1;

                 conn.count++;

                 if(conn.count==conn.connects && conn.connects>1) { //recalculate time and distribute new speeds

                      conn.recalcSpeeds();

                      conn.roundno++;

                      conn.count=0;

                 }

            } else {

                 if(conn.connects>1 && value!=conn.roundno) {  //someway ahead of the current round -- VERY BAD!

                      System.out.println("PARTICIPANT " + value2 + " WAY TOO FAST");

                 }   

                 conn.time[value2-1]=value1; //store round time

                 conn.theDate = new Date();

                 conn.report[value2-1]=conn.theDate.getTime(); //store report time

                 conn.count++;

                 if(conn.count==conn.connects && conn.connects>1) { //recalculate time and distribute new speeds

                      conn.recalcSpeeds();

                      conn.roundno++;

                      conn.count=0;

                 }

            }   

        }       

              else if(command.charAt(0)=='9' && command.charAt(1)=='2') {

                  conn.mode2++;

                  conn.checkMode2();

              }

              else if(command.charAt(0)=='9' && command.charAt(1)=='3') {

                  conn.mode3++;

                  conn.checkMode3();

              }

              else if(command.charAt(0)=='9' && command.charAt(1)=='8') {

               conn.details = command.substring(2) + "\n";

               conn.writeDetails(conn.details,1);

        }

              else if(command.charAt(0)=='9' && command.charAt(1)=='9') {

               conn.details = command.substring(2) + "\n";

               conn.writeDetails(conn.details,1);

              } else {   

                            conn.writeToAll(command);

                            System.out.println(command);

                        }   

          }

}