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();
+ }
}