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 passes to telnet consoles, 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);
}
}
}