Author: bdonlan
Date: 2005-01-14 20:36:45 -0500 (Fri, 14 Jan 2005)
New Revision: 599
Added:
trunk/misc/javer/src/javer/CMod.java
trunk/misc/javer/src/javer/GameMod.java
trunk/misc/javer/src/javer/TimedInvoker.java
trunk/misc/javer/src/javer/TimerThread.java
Modified:
trunk/misc/javer/
Log:
[EMAIL PROTECTED]: bdonlan | 2005-01-14 20:34:20 -0500
Import of Haver CMod. This should probably be moved into a seperate project.
Property changes on: trunk/misc/javer
___________________________________________________________________
Name: svk:merge
- 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk/misc/javer:16424
+ 1f59643a-e6e5-0310-bc24-f7d4c744f460:/haver/local/trunk/misc/javer:16426
Added: trunk/misc/javer/src/javer/CMod.java
===================================================================
--- trunk/misc/javer/src/javer/CMod.java 2005-01-14 21:07:21 UTC (rev
598)
+++ trunk/misc/javer/src/javer/CMod.java 2005-01-15 01:36:45 UTC (rev
599)
@@ -0,0 +1,177 @@
+/*
+ * CMod.java
+ *
+ * Created on January 14, 2005, 7:03 PM
+ */
+
+package javer;
+import java.util.*;
+import java.io.*;
+import java.math.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public class CMod extends GameMod {
+
+ boolean conspiracyExists = false;
+ boolean polling = false;
+ String innocent = null;
+ Map pollresults = null;
+ String homechannel;
+ Object pollTimer = null;
+
+ /** Creates a new instance of CMod */
+ public CMod(String homechannel) {
+ super();
+ this.homechannel = homechannel;
+ }
+
+ protected void eventPrivateNormalMessage(String who, String arg) throws
java.io.IOException {
+ if (polling) {
+ String val = arg.toLowerCase();
+ boolean choice;
+ if (val.equals("yes"))
+ choice = true;
+ else if (val.equals("no"))
+ choice = false;
+ else {
+ sendPrivateNormalMessage(who, "Huh?");
+ super.eventPrivateNormalMessage(who, arg);
+ return;
+ }
+ if (pollresults.containsKey(who)) {
+ sendPrivateNormalMessage(who, "You cannot change your
choice.");
+ } else {
+ Boolean value = new Boolean(choice);
+ pollresults.put(who, value);
+ sendPrivateNormalMessage(who, "Noted.");
+ if (pollresults.size() == players.size()) {
+ tallyResults();
+ }
+ }
+ }
+ super.eventPrivateNormalMessage(who, arg);
+ }
+
+ protected void eventIdentAccepted() throws java.io.IOException {
+ super.eventIdentAccepted();
+ join(homechannel);
+ }
+
+ public void endGame() throws java.io.IOException {
+ polling = false;
+ if (pollTimer != null) {
+ TimedInvoker.unschedule(pollTimer);
+ }
+ pollresults = null;
+ innocent = null;
+ pollTimer = null;
+ super.endGame();
+ }
+
+ public void beginGame() throws java.io.IOException {
+ Random r = new Random();
+ conspiracyExists = r.nextBoolean();
+ if (conspiracyExists) {
+ Object[] playerarray = players.toArray();
+ innocent = (String)playerarray[r.nextInt(playerarray.length)];
+ }
+ Iterator pi = players.iterator();
+ while (pi.hasNext()) {
+ String uid = (String)pi.next();
+ if (uid.equals(innocent) || !conspiracyExists) {
+ sendPrivateNormalMessage(uid, "You are an innocent in this
game.");
+ } else {
+ sendPrivateNormalMessage(uid, "You are a conspirator, and the
innocent is " + innocent);
+ }
+ }
+ sendNormalMessage(homechannel, "A game of Conspiracy has begun! You
have 10 minutes before polling phase begins.");
+ pollTimer = TimedInvoker.invokeAfter(10 * 60 * 1000, new Runnable() {
+ public void run() {
+ try {
+ beginPolling();
+ } catch (IOException e) {
+ eventIOException(e);
+ }
+ }
+ });
+ super.beginGame();
+ }
+
+ protected void beginPolling() throws IOException {
+ if (!playing)
+ return;
+ sendNormalMessage(homechannel, "Time's up! Please /msg me with 'yes'" +
+ " if you think there is a conspiracy, or 'no' if you believe" +
+ " there is no conspiracy.");
+ pollresults = new HashMap(players.size());
+ polling = true;
+ }
+
+ protected void tallyResults() throws IOException {
+ Set winners;
+ if (conspiracyExists) {
+ boolean innocentWins;
+ innocentWins = ((Boolean)pollresults.get(innocent)).booleanValue();
+ if (innocentWins)
+ winners = Collections.singleton(innocent);
+ else {
+ winners = new HashSet(players);
+ winners.remove(innocent);
+ }
+ } else {
+ Iterator it = players.iterator();
+ winners = new HashSet();
+ while (it.hasNext()) {
+ String uid = (String)it.next();
+ Boolean result = (Boolean)pollresults.get(uid);
+ if (!result.booleanValue())
+ winners.add(uid);
+ }
+ }
+ Iterator it = players.iterator();
+ sendNormalMessage(homechannel,
+ "All polls are in. The results are as follows:");
+ /* field lengths: nick 15, poll 3, win 3 */
+ sendNormalMessage(homechannel,
+ "NICK RES WIN");
+ sendNormalMessage(homechannel,
+ "=======================");
+ while (it.hasNext()) {
+ String uid = (String)it.next();
+ String nick = (String)channelMembers.get(uid);
+ boolean won = winners.contains(uid);
+ boolean vote = ((Boolean)pollresults.get(uid)).booleanValue();
+ while(nick.length() < 15) {
+ nick = nick + " ";
+ }
+ String msg = nick;
+ if (vote)
+ msg = msg + " Y ";
+ else
+ msg = msg + " N ";
+ if (won)
+ msg = msg + " Y ";
+ else
+ msg = msg + " N ";
+ sendNormalMessage(homechannel, msg);
+ }
+ sendNormalMessage(homechannel,
+ "=======================");
+ sendNormalMessage(homechannel,
+ "Game over. Thanks for playing!");
+ endGame();
+ }
+
+ public static void main(String[] args) throws Exception {
+ CMod mod = new CMod(args[3]);
+ mod.connect(args[0], args[1], Integer.decode(args[2]).intValue());
+ }
+
+ protected void eventDebugMessage(String s) throws IOException {
+ //log("DEBUG", s);
+ super.eventDebugMessage(s);
+ }
+}
Property changes on: trunk/misc/javer/src/javer/CMod.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/misc/javer/src/javer/GameMod.java
===================================================================
--- trunk/misc/javer/src/javer/GameMod.java 2005-01-14 21:07:21 UTC (rev
598)
+++ trunk/misc/javer/src/javer/GameMod.java 2005-01-15 01:36:45 UTC (rev
599)
@@ -0,0 +1,154 @@
+/*
+ * GameMod.java
+ *
+ * Created on January 14, 2005, 6:16 PM
+ */
+
+package javer;
+import java.util.*;
+import java.io.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+public abstract class GameMod extends HaverClient {
+
+ protected boolean connected = false;
+ protected boolean joined = false;
+ protected boolean playing = false;
+ protected boolean starting = false;
+ protected String channel = null;
+ protected Map channelMembers = null; /* UID -> nick */
+ protected Set players = null; /* UID */
+ protected Object joinTimer = null;
+
+ /** Creates a new instance of GameMod */
+ protected GameMod() {
+ }
+
+ protected void log(String level, String message) {
+ System.err.println(level + ": " + message);
+ }
+
+ public void dropPlayer(String requestor, String dropee) {
+ /* TODO */
+ }
+
+ protected void eventChannelPart(String where) throws IOException {
+ joined = false;
+ endGame();
+ channelMembers = null;
+ channel = null;
+ super.eventChannelPart(where);
+ }
+
+ protected void eventChannelJoin(String where) throws IOException {
+ if (joined) {
+ log("CRITICAL", "Joined an extra channel: " + where);
+ return;
+ }
+ joined = true;
+ channel = where;
+ listChannel(where);
+ super.eventChannelJoin(where);
+ }
+
+ protected boolean eventIOException(IOException e) {
+
+ boolean retValue;
+
+ retValue = super.eventIOException(e);
+ return retValue;
+ }
+
+ protected void eventIdentFailed(String why, String[] args) throws
IOException {
+
+ super.eventIdentFailed(why, args);
+ }
+
+ protected void eventChannelList(String where, Set names) throws
IOException {
+ Iterator it = names.iterator();
+ if (!where.equals(channel))
+ return;
+ channelMembers = new HashMap();
+ while (it.hasNext()) {
+ Object o = it.next();
+ channelMembers.put(o,o);
+ }
+ super.eventChannelList(where, names);
+ }
+
+ protected void eventNormalMessage(String where, String who, String arg)
throws IOException {
+ if (arg.equals("!join") && starting) {
+ if (players.contains(who)) {
+ sendPrivateNormalMessage(who, "You are already registered.");
+ } else {
+ players.add(who);
+ sendPrivateNormalMessage(who, "You are now registered.");
+ }
+ } else if (arg.equals("!abort") && (starting || playing)) {
+ abortGame();
+ } else if (arg.indexOf("!drop") == 0 && (starting || playing)) {
+ if (arg.length() == 0) {
+ dropPlayer(who, who);
+ } else {
+ if (arg.indexOf("!drop ") == 0) {
+ int i = "!drop ".length();
+ for (; i < arg.length(); i++) {
+ if (arg.charAt(i) != ' ')
+ break;
+ }
+ if (i != arg.length()) {
+ dropPlayer(who, arg.substring(i));
+ }
+ }
+ }
+ } else if (arg.equals("!start") && !(playing || starting)) {
+ starting = true;
+ players = new HashSet();
+ sendNormalMessage(where, "A new game has begun. Type !join in the
next 30 seconds to join.");
+ joinTimer = TimedInvoker.invokeAfter(30 * 1000, new Runnable() {
+ public void run () {
+ try {
+ beginGame();
+ } catch (IOException e) {
+ eventIOException(e);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ joinTimer = null;
+ }
+ });
+ }
+ super.eventNormalMessage(where, who, arg);
+ }
+
+ protected void eventDisconnected() throws IOException {
+ endGame();
+ super.eventDisconnected();
+ }
+
+ protected void eventIdentAccepted() throws IOException {
+ connected = true;
+ super.eventIdentAccepted();
+ }
+
+ public void endGame() throws IOException {
+ playing = starting = false;
+ players = null;
+ if (joinTimer != null) {
+ TimedInvoker.unschedule(joinTimer);
+ joinTimer = null;
+ }
+ }
+
+ public void abortGame() throws IOException {
+ endGame();
+ sendNormalMessage(channel, "Game aborted");
+ }
+
+ public void beginGame() throws IOException {
+ playing = true;
+ }
+}
Property changes on: trunk/misc/javer/src/javer/GameMod.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/misc/javer/src/javer/TimedInvoker.java
===================================================================
--- trunk/misc/javer/src/javer/TimedInvoker.java 2005-01-14 21:07:21 UTC
(rev 598)
+++ trunk/misc/javer/src/javer/TimedInvoker.java 2005-01-15 01:36:45 UTC
(rev 599)
@@ -0,0 +1,37 @@
+/*
+ * TimedInvoker.java
+ *
+ * Created on January 14, 2005, 7:40PM
+ */
+
+package javer;
+import java.util.*;
+import java.io.*;
+import java.math.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+final class TimedInvoker {
+
+ static TimerThread tt = new TimerThread();
+
+ private TimedInvoker() {
+ throw new IllegalStateException("Cannot instantiate a singleton
class");
+ }
+
+ public static Object invokeAt(long absoluteTimeMillis, Runnable invokee) {
+ return tt.addTimer(absoluteTimeMillis, invokee);
+ }
+
+ public static Object invokeAfter(long deltaMillis, Runnable invokee) {
+ return tt.addTimer(System.currentTimeMillis() + deltaMillis,
+ invokee);
+ }
+
+ public static boolean unschedule(Object tag) {
+ return tt.cancelTimer(tag);
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/misc/javer/src/javer/TimedInvoker.java
___________________________________________________________________
Name: svn:eol-style
+ native
Added: trunk/misc/javer/src/javer/TimerThread.java
===================================================================
--- trunk/misc/javer/src/javer/TimerThread.java 2005-01-14 21:07:21 UTC (rev
598)
+++ trunk/misc/javer/src/javer/TimerThread.java 2005-01-15 01:36:45 UTC (rev
599)
@@ -0,0 +1,118 @@
+/*
+ * TimerThread.java
+ *
+ * Created on January 14, 2005, 7:47 PM
+ */
+
+package javer;
+import java.util.*;
+
+/**
+ *
+ * @author bdonlan
+ */
+class TimerThread implements Runnable {
+
+ class Timer {
+ Runnable evt;
+ long when;
+ }
+
+ Thread thread = null;
+ SortedMap queue = new TreeMap();
+
+ protected void notifyThread() {
+ synchronized (queue) {
+ if (thread == null || !thread.isAlive()) {
+ thread = new Thread(this);
+ //System.out.println("TT: spawning");
+ thread.start();
+ return;
+ }
+ //System.out.println("TT: interrupting");
+ thread.interrupt();
+ }
+ }
+
+ protected synchronized Object addTimer(long when, Runnable event) {
+ Set slot;
+ Timer te = new Timer();
+ Long oWhen = new Long(when);
+ te.evt = event;
+ te.when = when;
+ synchronized (queue) {
+ slot = (Set)queue.get(oWhen);
+ if (slot == null) {
+ slot = new LinkedHashSet();
+ }
+ slot.add(te);
+ queue.put(oWhen, slot);
+ //System.out.println("TT: add queuelen=" + queue.size());
+ //System.out.println("TT: add slotlen=" + slot.size());
+ notifyThread();
+ }
+ return te;
+ }
+
+ protected synchronized boolean cancelTimer(Object tag) {
+ Timer te = (Timer) tag;
+ Long when = new Long(te.when);
+ synchronized (queue) {
+ Set slot = (Set)queue.get(when);
+ if (slot == null)
+ return false;
+ slot.remove(te);
+ if (slot.isEmpty())
+ queue.remove(when);
+ /* We don't need to notify the thread; if this slot is next then
+ * the thread will just go back to sleep or die once it discovers
+ * the first slot time has changed.
+ */
+ return true;
+ }
+ }
+
+ public void run() {
+ if (Thread.currentThread() != thread)
+ return;
+ while (true) {
+ long nextSlot, delta, now;
+ Set slot = null;
+ now = System.currentTimeMillis();
+ synchronized (queue) {
+ Long firstkey;
+ if (queue.size() == 0) {
+ /* No work? We die. */
+ //System.out.println("TT: no work, killing thread");
+ thread = null;
+ return;
+ }
+ firstkey = (Long)queue.firstKey();
+ nextSlot = firstkey.longValue();
+ //System.out.println("TT: nxS=" + nextSlot + "\nTT: now=" +
now);
+ if (nextSlot <= now) {
+ //System.out.println("TT: pop=" + nextSlot);
+ slot = (Set) queue.remove(firstkey);
+ }
+ }
+ if (slot != null) {
+ Iterator it = slot.iterator();
+ //System.out.println("TT: slotsize=" + slot.size());
+ while (it.hasNext()) {
+ Timer te = (Timer)it.next();
+ //System.out.println("TT: invokeLater("+te.evt+")");
+ java.awt.EventQueue.invokeLater(te.evt);
+ }
+ continue;
+ }
+ delta = nextSlot - now;
+ try {
+ thread.sleep(delta);
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ TimerThread() {
+ }
+}
+
Property changes on: trunk/misc/javer/src/javer/TimerThread.java
___________________________________________________________________
Name: svn:eol-style
+ native