Author: bdonlan
Date: 2005-05-22 22:54:29 -0400 (Sun, 22 May 2005)
New Revision: 710

Modified:
   trunk/clients/Javer2/src/haver/Client.java
   trunk/clients/Javer2/src/haver/NonblockingOutputStream.java
   trunk/clients/Javer2/src/javer2/CMod.java
Log:
src/haver/NonblockingOutputStream.java:
  * Copy buffers to avoid problems with later modifications
src/haver/Client.java:
  * Process S: FROM properly
  * sendPrivateMessage, sendPublicMessage: new
src/javer2/CMod.java:
  * Game logic


Modified: trunk/clients/Javer2/src/haver/Client.java
===================================================================
--- trunk/clients/Javer2/src/haver/Client.java  2005-05-22 20:48:48 UTC (rev 
709)
+++ trunk/clients/Javer2/src/haver/Client.java  2005-05-23 02:54:29 UTC (rev 
710)
@@ -696,16 +696,21 @@
         sendLine(cmd);
     }
     
+    public void sendPublicMessage(String channel, String type, String arg) 
throws IOException {
+        String[] args = {arg};
+        sendPublicMessage(channel, type, args);
+    }
+    
     protected void handle_FROM(String[] args) throws IOException {
         if (args.length < 3) {
             // XXX: exception?
             System.err.println("Short FROM message from haver server");
             return;
         }
-        String user = args[0];
-        String type = args[1];
-        String margs[] = new String[args.length - 2];
-        System.arraycopy(args, 2, margs, 0, args.length - 2);
+        String user = args[1];
+        String type = args[2];
+        String margs[] = new String[args.length - 3];
+        System.arraycopy(args, 3, margs, 0, margs.length);
         
         dist.onPrivateMessage(this, user, type, margs);
     }
@@ -718,4 +723,9 @@
         System.arraycopy(margs, 0, args, 3, margs.length);
         sendLine(args);
     }
+    
+    public void sendPrivateMessage (String target, String type, String arg) 
throws IOException {
+        String[] args = {arg};
+        sendPrivateMessage(target, type, args);
+    }
 }

Modified: trunk/clients/Javer2/src/haver/NonblockingOutputStream.java
===================================================================
--- trunk/clients/Javer2/src/haver/NonblockingOutputStream.java 2005-05-22 
20:48:48 UTC (rev 709)
+++ trunk/clients/Javer2/src/haver/NonblockingOutputStream.java 2005-05-23 
02:54:29 UTC (rev 710)
@@ -154,7 +154,12 @@
     public void write(byte[] b) throws IOException {
         if (b.length == 0)
             return;
-        //System.out.println("write called");
+        byte[] bc = new byte[b.length];
+        System.arraycopy(b, 0, bc, 0, b.length);
+        write_(bc);
+    }
+    
+    protected void write_(byte[] b) throws IOException {
         synchronized(th) {
             if (pending_exception != null)
                 throw pending_exception;
@@ -270,9 +275,8 @@
      */
 
     public void write(int b) throws IOException {
-        byte[] a = new byte[1];
-        a[0] = (byte) b;
-        write(a);
+        byte[] a = {(byte)b};
+        write_(a);
     }
     
     /**
@@ -286,17 +290,9 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public void write(byte[] b, int off, int len) throws IOException {
-        if (len == 0)
-            return;
-        if (len < 0)
-            throw new IllegalArgumentException("len must not be negative");
-        if (off + len > b.length)
-            throw new IllegalArgumentException("off + len > b.length");
         byte[] buffer = new byte[len];
-        int i;
-        for (i = 0; i < len; i++)
-            buffer[i] = b[off + i];
-        write(buffer);
+        System.arraycopy(b, off, buffer, 0, len);
+        write_(buffer);
     }
 
 }

Modified: trunk/clients/Javer2/src/javer2/CMod.java
===================================================================
--- trunk/clients/Javer2/src/javer2/CMod.java   2005-05-22 20:48:48 UTC (rev 
709)
+++ trunk/clients/Javer2/src/javer2/CMod.java   2005-05-23 02:54:29 UTC (rev 
710)
@@ -8,6 +8,7 @@
 import haver.*;
 import java.util.*;
 import java.text.*;
+import java.io.*;
 
 /**
  *
@@ -16,6 +17,7 @@
 public class CMod extends Callback {    
     Client c = new Client();
     Timer t = new Timer(true);
+    String channel;
     
     protected void ping() {
         logMessage("ping!");
@@ -29,6 +31,7 @@
     
     /** Creates a new instance of CMod */
     public CMod(String host, int port, String name, String channel) throws 
Throwable {
+        this.channel = channel;
         c.addNotify(this);
         c.syncConnect(host, port, name);
         ping();
@@ -46,4 +49,202 @@
         new CMod("localhost", 13456, "cmod", "lobby");
     }
     
+    static final int STATE_IDLE = 0;
+    static final int STATE_JOIN = 1;
+    static final int STATE_CHAT = 2;
+    static final int STATE_VOTE = 3;
+    
+    static final int joinTimeout = 30;
+    static final int chatTimeout = 3; // XXX
+    
+    int current_state = 0;
+    
+    HashSet players = null;
+    HashMap votes   = null;
+    TimerTask startTask = null;
+    TimerTask voteTask  = null;
+    
+    public synchronized void reset() {
+        current_state = 0;
+        players = null;
+        votes = null;
+        if (startTask != null)
+            startTask.cancel();
+        startTask = null;
+        if (voteTask != null)
+            voteTask.cancel();
+        voteTask = null;
+    }
+    
+    public void onDisconnected(Client source, java.io.IOException e) throws 
java.io.IOException {
+        System.exit(0);
+    }
+
+    public synchronized void onPrivateMessage(Client source, String from, 
String type, String[] args) throws java.io.IOException {
+        if (current_state != STATE_VOTE) return;
+        boolean vote;
+        if (args[0].equals("yes"))
+            vote = true;
+        else if (args[0].equals("no"))
+            vote = false;
+        else return;
+        
+        if (votes.containsKey(from)) {
+            c.sendPrivateMessage(from, "say", "You have already voted.");
+            return;
+        }
+        
+        votes.put(from, new Boolean(vote));
+        c.sendPrivateMessage(from, "say", "Your vote has been recorded.");
+        tallyVotes();
+    }
+
+    public synchronized void onPublicMessage(Client source, String channel, 
String from, String type, String[] args) throws java.io.IOException {
+        
+        if (!channel.equals(this.channel)) return;
+        if (!type.equals("say")) return;
+        
+        if (current_state != STATE_IDLE && args[0].equals("!reset")) reset();
+        
+        switch (current_state) {
+            case STATE_IDLE:
+                idleMsg(from, args[0]);
+                break;
+            case STATE_JOIN:
+                joinMsg(from, args[0]);
+                break;
+            default:
+                return;
+        }
+    }
+    
+    public void idleMsg(String from, String msg) throws IOException {
+        if (!msg.equals("!start")) return;
+        current_state = STATE_JOIN;
+        startTask = new TimerTask() {
+            public void run() {
+                try {
+                    startGame();
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                }
+            }
+        };
+        t.schedule(startTask, joinTimeout * 1000);
+        c.sendPublicMessage(channel, "say",
+                "A game of conspiracy has begun (or has it?). You have " +
+                joinTimeout + " seconds to type '!join'");
+        players = new HashSet();
+    }
+    
+    public void joinMsg(String from, String msg) throws IOException {
+        if (!msg.equals("!join")) return;
+        if (players.contains(from)) {
+            c.sendPrivateMessage(from, "say", "You have already joined.");
+            return;
+        }
+        players.add(from);
+        c.sendPublicMessage(channel, "say", from + " has been added to the 
list of players.");
+    }
+    
+    String innocent = null;
+    
+    public synchronized void startGame() throws IOException {
+        if (current_state != STATE_JOIN) return;
+        if (players.size() < 3) {
+            c.sendPublicMessage(channel, "say", "Not enough players, 
aborting.");
+            reset();
+            return;
+        }
+        current_state = STATE_CHAT;
+        Random r = new Random();
+        if (r.nextBoolean()) {
+            Object[] players_a = players.toArray();
+            innocent = (String)players_a[r.nextInt(players_a.length)];
+        }
+        Iterator i = players.iterator();
+        while (i.hasNext()) {
+            String current = (String)i.next();
+            if (innocent == null || innocent.equals(current)) {
+                c.sendPrivateMessage(current, "say", "You are an innocent in 
this game.");
+            } else {
+                c.sendPrivateMessage(current, "say", "You are a conspirator, 
and the innocent is " + innocent);
+            }
+        }
+        c.sendPublicMessage(channel, "say", "The game is afoot! You have " + 
chatTimeout + " seconds to point fingers before I'll come back demanding 
answers from you lot.");
+        voteTask = new TimerTask() {
+            public void run() {
+                try { startVote(); }
+                catch (Throwable t) { t.printStackTrace(); }
+            }
+        };
+        t.schedule(voteTask, 1000 * chatTimeout);
+    }
+    
+    public synchronized void startVote() throws IOException {
+        if (current_state != STATE_CHAT) return;
+        c.sendPublicMessage(channel, "say", "Time's up, so stop these baseless 
public accusations, and begin private accusations. To me.");
+        c.sendPublicMessage(channel, "say", "Message me with 'yes' if you 
think there's a conspiracy, or 'no' if you think it's all a bunch of baseless 
liberal propaganda.");
+        current_state = STATE_VOTE;
+        votes = new HashMap();
+    }
+    
+    public synchronized void tallyVotes() throws IOException {
+        if (current_state != STATE_VOTE) return;
+        if (votes.size() < players.size()) return;
+        HashMap wins = new HashMap();
+        if (innocent != null) {
+            boolean innocent_vote = 
((Boolean)votes.get(innocent)).booleanValue();
+            Iterator i = players.iterator();
+            while (i.hasNext()) {
+                String player = (String)i.next();
+                boolean win;
+                if (player.equals(innocent))
+                    win = innocent_vote;
+                else
+                    win = !innocent_vote;
+                wins.put(player, new Boolean(win));
+            }
+        } else {
+            Iterator i = players.iterator();
+            while (i.hasNext()) {
+                String player = (String)i.next();
+                boolean vote = ((Boolean)votes.get(player)).booleanValue();
+                wins.put(player, new Boolean(!vote));
+            }
+        }
+        
+        String namehead = "NAME        ";
+        String votehead = "VOTE";
+        String winshead = "WIN?";
+        
+        c.sendPublicMessage(channel, "say", namehead + " " + votehead + " " + 
winshead + " ");
+        Iterator i = players.iterator();
+        while (i.hasNext()) {
+            String player = (String)i.next();
+            Boolean vote_o = (Boolean)votes.get(player);
+            Boolean win_o = (Boolean)wins.get(player);
+            boolean vote_b = vote_o.booleanValue();
+            boolean win_b = win_o.booleanValue();
+            String vote_s = vote_b ? "YES  " : "NO   ";
+            String win_s = win_b ? "YES " : "NO  ";
+            
+            StringBuffer buf = new StringBuffer(namehead.length() + 11);
+            
+            int length = player.length();
+            if (length > namehead.length())
+                length = namehead.length();
+            String snippedname = player.substring(0, length);
+            int pad = namehead.length() - length + 1;
+            buf.append(snippedname);
+            while (pad-- > 0)
+                buf.append(' ');
+            buf.append(vote_s);
+            buf.append(win_s);
+            c.sendPublicMessage(channel, "say", buf.toString());
+        }
+        
+        c.sendPublicMessage(channel, "say", "Game Over. Thanks for playing!");
+        reset();
+    }
 }


Reply via email to