// MorgenGrauen MUDlib
//
// living/comm.c -- communiction module for livings
//
// $Id$

#pragma strong_types,save_types
#pragma no_clone
#pragma range_check

#include <defines.h>
#include <thing/language.h>
#define NEED_PROTOTYPES
#include <living/comm.h>
#undef NEED_PROTOTYPES

void create_super()
{
  set_next_reset(-1);
}

protected string comm_guess_action() {
  string cmd;
  string action = query_verb();
  // Die Aktionen sind intern in der Regel nach den haeufigsten Kommandoverben
  // dieser Aktion benannt. Bei einigen Aktionen sind mehrere Kommandoverben
  // ueblich, die sollen hier noch abgehandelt werden.
  switch(action) {
    case "nehme":
      // MA_TAKE == nimm
      action = MA_TAKE;
      break;

    case "gebe":
      // MA_GIVE == "gib"
      action = MA_GIVE;
      break;
    
    case "norden":
    case "nordosten":
    case "osten":
    case "suedosten":
    case "sueden":
    case "suedwesten":
    case "westen":
    case "nordwesten":
    case "oben":
    case "unten":
    case "betrete":
    case "verlasse":
    case "teleport":
    case "teleportiere":
      action = MA_MOVE;
      break;

    case "unt":
      action = MA_LOOK;
      break;

    case "wirf":
      if (strstr(query_command(), " weg") > -1)
        action = MA_PUT;
      break;

    case "stecke":
      cmd = query_command();
      if (strstr(cmd, " weg") > -1)
        action = MA_UNWIELD;
      else if (strstr(cmd," in ") > -1)
        action = MA_PUT;
      break;

    case "ziehe":
      cmd = query_command();
      if (strstr(cmd, " an") > -1)
        action = MA_WEAR;
      else if (strstr(cmd, " aus") > -1)
        action = MA_UNWEAR;
      break;

    case "esse":
    case "friss":
      action = MA_EAT;
      break;

    case "saufe":
      action = MA_DRINK;
      break;

    case "hoere":
      //MA_LISTEN == lausche
      action = MA_LISTEN;
      break;
    case "lese":
      action = MA_READ;
      break;

    case ":":
    case ";":
      action = MA_EMOTE;
      break;

    case "zerbreche":
    case "zerstoere":
    case "verbrenne":
    case "entsorge":
      action = MA_REMOVE;
      break;
  }
  return action;
}

protected int comm_guess_message_type(string action, mixed origin) {
  // everything not mentioned in the switch becomes MT_LOOK.
  switch(action) {
    case MA_FIGHT:
      // Kampf kann man meisten sowohl sehen als auch hoeren.
      return MT_LOOK | MT_LISTEN;
    case MA_LISTEN:
    case MA_SAY:
      return MT_LISTEN;
    case MA_FEEL:
      return MT_FEEL;
    case MA_SMELL:
      return MT_SMELL;
    case MA_CHANNEL:
      return MT_COMM | MT_FAR;
    case MA_EMOTE:
      if (objectp(origin)
          && environment(origin) == environment())
        return MT_COMM;
      else
        return MT_COMM | MT_FAR;
    case MA_SHOUT:
      return MT_LISTEN | MT_FAR;
  }
  // die meisten Aktionen sind zumindest sichtbar...
  return MT_LOOK;
}

// ReceiveMsg() wird in <player/comm.c> und <npc/comm.c> implementiert und ist
// hier nicht erforderlich (Cross-Defintion von LPC sei Dank).
//public varargs int ReceiveMsg(string msg, int msg_type, string msg_action,
//                              string msg_prefix, object origin)
//{}


// Wrapper fuer ReceiveMsg()

// Bekommt ein wave_s oder davon geerbte Struct uebergeben, welche daher
// mindestens Nachricht, Typ und Prefix enthaelt. Ist ansonsten
// funktionsgleich zu ReceiveMsg().
public int ReceiveWave(struct wave_s wave, string msg_action, object origin)
{
  if (!wave) return MSG_FAILED;
  return ReceiveMsg(wave.msg, wave.type, msg_action, wave.prefix,
                    origin);
}

// Bekommt ein wave_s oder davon geerbte Struct uebergeben, welche daher
// mindestens Nachricht, Typ und Prefix enthaelt. Wird ein wave_dyn_s
// uebergeben und ist das <cl>-Element eine Closure, wird diese ausgewertet
// und kann Nachricht, Typ und Prefix veraendern. Ansonsten ist diese Funktion
// funktionsgleich zu ReceiveWave().
public int ReceiveDynWave(struct wave_s wave, string msg_action, object origin)
{
  if (!wave) return MSG_FAILED;
  // Falls ein wave_dyn_s uebergeben wurde, ist ein Element cl enthalten und
  // -> gibt das zurueck. ( . funktioniert nicht, weil der Compiler von einem
  // wave_s ausgeht.
  if (closurep(wave->cl))
      wave = funcall(wave->cl, wave);
  return ReceiveMsg(wave.msg, wave.type, msg_action, wave.prefix,
                    origin);
}

public int ReceiveNotify(string msg, string action)
{
  // Da MT_NOTIFICATION immer zugestellt wird, ist keine Fehlerbehandlung
  // notwendig.
  return ReceiveMsg(
    msg,
    // MSG_DONT_IGNORE waere wegen MT_NOTIFICATION inhaltlich nicht noetig,
    // spart aber ein paar Ticks.
    MT_NOTIFICATION | MSG_BS_LEAVE_LFS | MSG_DONT_IGNORE,
    action);
}

public int ReceiveTeilemit(string msg)
{
  // Blockierte Sinne sind hier kein Problem, ergo keine Fehlerbehandlung.
  return ReceiveMsg(
    replace_personal(msg, ({previous_object(), this_player()}) - ({0}), 1),
    MT_COMM | MT_FAR | MSG_BS_LEAVE_LFS | MSG_DONT_STORE,
    MA_TELL,
    previous_object().Name(WER, 1) + "teilt Dir mit: ");
}

public int ReceiveMultiSense(struct wave_s *msgs,
    string action = comm_guess_action(), int commontypes = 0)
{
  int res;
  foreach(struct wave_s wave : msgs)
  {
    // Pruefung auf != MSG_SENSE_BLOCK statt Erfolg, weil ein anderer Fehler
    // (insb. aufgrund ignoriere) fuer alle Alternativen ebenso auftritt.
    res = ReceiveMsg(
          replace_personal(wave.msg, ({previous_object(), this_player()}),1),
          wave.type | MSG_BS_LEAVE_LFS | commontypes, action, wave.prefix);
    if (res != MSG_SENSE_BLOCK)
    {
      break;
    }
  }
  return res;
}

public int ReceiveSay(string msg,
    string prefix = previous_object().Name(WER, 1) + " sagt: ",
    struct wave_s *alt =
        ({(<wave_s>
            msg: "@WER1 bewegt die Lippen, Du hoerst jedoch nichts.",
            type: MT_LOOK)})
        )
{
  // Nachricht in struct konvertieren, ans Anfang vom Array stellen
  alt = ({(<wave_s> msg: msg, prefix: prefix, type: MT_LISTEN)}) + alt;
  // Rest macht ReceiveMultiSense()
  return ReceiveMultiSense(alt, MA_SAY, MSG_BS_LEAVE_LFS);
}

