package net.sourceforge.pain.logic.fn; import net.sourceforge.pain.data.*; import net.sourceforge.pain.data.type.*; import net.sourceforge.pain.logic.fn.util.*; import net.sourceforge.pain.network.console.*; import java.util.*; /** MessageOutFn template definition: $$ - means '$' ascii character, this is not parameter. $xN - means parameter (N=0-9) all paramter look for values in args[] array so we haave invariant: args.length = number of parameters X: lowercase: first param UPPERCASE: second param t,d - (text)argiment is a java.lang.String (t=t1, T = t2 - compatibility) n - interactive name p - interactive desc This parameters will get clarified in one of the next versions: e,E - Result is 'he', 'she', or 'it', depending on the sex/gender of arg (LogicalObject). (default he) m,M - Result is 'him', 'her', or 'it', depending on the sex/gender of arg (LogicalObject).(default his) s,S - Result is 'his', 'her', or 'its', depending on the sex/gender of arg (LogicalObject).(default his) TO_ONE: = to messageRecipient only TO_SPACE: = to every receptive object in this space except messageRecipient WARN: single thread model!!! */ public final class MessageOutFn { private static final Map preparedTemplates = new HashMap(); private static final Object args[] = new Object[9]; public static void outSpace(LogicalObject actor, String template, Object arg1) { outSpace(actor, template, arg1, null); } public static void outSpace(LogicalObject actor, String template, Object arg1, Object arg2) { outSpace(actor, template, arg1, arg2, Receptive.SEE); } public static void outSpace(LogicalObject actor, String template, Object arg1, Object arg2, int receptionType) { args[0] = arg1; args[1] = arg2; _outSpace(actor, null, template, args, receptionType); args[0] = null; args[1] = null; } public static void outSpaceNoVictim(LogicalObject actor, Interactive victim, String template) { outSpaceNoVictim(actor, victim, template, null); } public static void outSpaceNoVictim(LogicalObject actor, Interactive victim, String template, Object arg1) { outSpaceNoVictim(actor, victim, template, arg1, null); } public static void outSpaceNoVictim(LogicalObject actor, Interactive victim, String template, Object arg1, Object arg2) { outSpaceNoVictim(actor, victim, template, arg1, arg2, null, Receptive.SEE); } public static void outSpaceNoVictim(LogicalObject actor, Interactive victim, String template, Object arg1, Object arg2, Object arg3, int receptionType) { args[0] = arg1; args[1] = arg2; args[2] = arg3; _outSpace(actor, victim, template, args, receptionType); args[0] = null; args[1] = null; args[2] = null; } public static void outOne(LogicalObject recipient, String template, Object arg1) { outOne(recipient, template, arg1, null); } public static void outOne(LogicalObject recipient, String template, Object arg1, Object arg2) { args[0] = arg1; args[1] = arg2; _outOne(recipient, prepareTemplate(template), args, Receptive.SEE); args[0] = null; args[1] = null; } private static void _outOne(LogicalObject obj, OutTemplate template, Object[] args, int receptionType) { Receptive rObj = (Receptive) obj.getRole(Receptive.class); if (rObj == null || !rObj.has(receptionType)) { return; } //today the only reception output is console, in next version reception outputs will be expanded (virtual consoles or something like that) Console console = ConsoleFn.getConsole(obj); if (console == null) { return; } String[] tokens = template.tokens; char[] params = template.params; int argN[] = template.argN; console.out(tokens[0]); for (int i = 0; i < params.length; i++) { final String value; Object arg = args[argN[i]]; switch (params[i]) { case 'T': case 'D': value = (String) arg; break; case 'N': Interactive inter1 = (Interactive) ((LogicalObject) arg).getRole(Interactive.class); if (inter1 == null) { throw new RuntimeException("arg" + argN[i] + " is not Interactive!"); } value = inter1.getName(); break; case 'P': Interactive inter2 = (Interactive) ((LogicalObject) arg).getRole(Interactive.class); if (inter2 == null) { throw new RuntimeException("arg" + argN[i] + " is not Interactive!"); } value = inter2.getDesc(); break; case 'E': value = LangUtil.he((LogicalObject) arg); break; case 'M': value = LangUtil.him((LogicalObject) arg); break; case 'S': value = LangUtil.his((LogicalObject) arg); break; default: throw new RuntimeException("Not supported type:" + params[i]); } // Log.debug("OUT:value'"+value+"'"); console.out(value); // Log.debug("OUT:token'"+template.tokens[i + 1]+"'"); console.out(template.tokens[i + 1]); } console.out("\n"); } private static void _outSpace(LogicalObject actor, LogicalObject victim, String template, Object[] args, int receptionType) { final Located actorL = (Located) actor.getRole(Located.class); final Located victimL = victim == null ? null : (Located) victim.getRole(Located.class); final OutTemplate t = prepareTemplate(template); Space space = actorL.getLocation(); for (Located obj = space.getFirstInSpace(); obj != null; obj = obj.getNextInSpace()) { if (obj != actorL && obj != victimL) { _outOne(obj, t, args, receptionType); } } } private static OutTemplate prepareTemplate(String templateStr) { OutTemplate template = (OutTemplate) preparedTemplates.get(templateStr); if (template == null) { template = new OutTemplate(templateStr); preparedTemplates.put(templateStr, template); } return template; } protected static final class OutTemplate { private static final char[] upper = new char[127]; static { upper['T'] = upper['t'] = 'T'; upper['D'] = upper['d'] = 'D'; upper['N'] = upper['n'] = 'N'; upper['P'] = upper['p'] = 'P'; upper['E'] = upper['e'] = 'E'; upper['M'] = upper['m'] = 'M'; upper['S'] = upper['s'] = 'S'; } public String[] tokens; // simple text between arguments public char[] params; // $, parameters public int[] argN; // argNum public OutTemplate(String templateStr) { int nParams = countParams(templateStr); params = new char[nParams]; argN = new int[nParams]; tokens = new String[nParams + 1]; // we always have N parameters and N+1 tokens // example: templateStr = '$n tells $T' ->""+n+" tells "+T+"" StringBuffer buff = new StringBuffer(); int index = 0; final int tLen = templateStr.length(); for (int i = 0; i < tLen; i++) { char c = templateStr.charAt(i); if (c == '$') { i++; c = templateStr.charAt(i); if (c == '$') { buff.append(c); } else { tokens[index] = (buff.length() == 0 ? "" : buff.toString()); buff.delete(0, buff.length()); char uc = c < 127 ? upper[c] : 0; if (uc == 0) { throw new RuntimeException("Illegal param value:" + c); } params[index] = uc; i++; int arg = 0; if (i < tLen) { arg = templateStr.charAt(i) - '0'; if (arg < 1 || arg > 9) { arg = 0; i--; } } if (arg == 0) { arg = c == uc ? 2 : 1; } argN[index] = arg - 1; // argN is started from 0 index++; } } else { buff.append(c); } } tokens[tokens.length - 1] = (buff.length() == 0 ? "" : buff.toString()); } private int countParams(String str) { int result = 0; for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c == '$') { i++; c = str.charAt(i); if (c != '$') { result++; } } } return result; } } public static final void out(Console outConsole, String text) { if (outConsole != null) { outConsole.out(text); } } public static final void outln(Console outConsole, String text) { if (outConsole != null) { outConsole.out(text); outConsole.out("\n"); } } /** * any reception type! * @param obj * @param message */ public static void outln(LogicalObject obj, String message) { Console c = ConsoleFn.getConsole(obj); if (c == null) { return; } outln(c, message); } public static void outln(LogicalObject obj, String message, int receptionType) { Receptive r = (Receptive) obj.getRole(Receptive.class); if (r == null || !r.has(receptionType)) { return; } Console c = ConsoleFn.getConsole(obj); if (c == null) { return; } outln(c, message); } public static void outSpace(Space space, String message) { for (Located obj = space.getFirstInSpace(); obj != null; obj = obj.getNextInSpace()) { outln(obj, message, Receptive.FEEL); } } }