pgplus/bin/
pgplus/help_files/
pgplus/port_redirector/
pgplus/src/configure/makefiles/
/*
 * Playground+ - channel.c
 * All new and improved channel code written by Silver (main, spod & zchannel)
 * ----------------------------------------------------------------------------
 * Serious rewrite of channel commands using generalisations, by blimey
 * saved on hundreds of lines of ghastly repeated code
 *
 * Repeated code? Me? Never .. oops [whistles innocently] -- Silver 
 */

#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>

#include "include/config.h"
#include "include/player.h"
#include "include/proto.h"

#ifdef INTERCOM
void ichan_wall(char *);
void i_chan(char *,...);
#include "include/intercom.h"
extern nameban *check_intercom_banished_name (char *);
#endif

/*
 * Shadow Realms channel code -- by blimey
 *
 */
char *how_to_say(char *str)
{
  for (; *str; str++);
  switch (*(--str))
  {
    case '?':
      return "asks";
    case '!':
      return "exclaims";
    default:
      return "says";
  }
}

/*
 * Here are the higher order definitions of channel commands -- blimey
 *
 */
void channel_emote(player * p, char *str,
		   void (*the_wall) (char *,...))
{

  if (p->flags & FROGGED)
    str = "shakes a broken rattle";

  if ((*str == '`') || (*str == '\''))
    the_wall("%s%s^N\n", p->name, str);
  else
    the_wall("%s %s^N\n", p->name, str);
}

void channel_say(player * p, char *str,
		 void (*the_wall) (char *,...))
{

  the_wall("%s %s '%s%s^N'\n",
	   p->name,
	   how_to_say(str),
	   str,
	   (p->flags & FROGGED ? " and WHERE'S MY RATTLE?!" : ""));
}

void channel_sing(player * p, char *str,
		  void (*the_wall) (char *,...))
{

  the_wall("%s sings o/~ %s ^No/~%s\n",
	   p->name,
	   str,
	   (p->flags & FROGGED ? " while shaking a broken rattle" : ""));
}

void channel_think(player * p, char *str,
		   void (*the_wall) (char *,...))
{

  the_wall("%s thinks %s. o O ( %s ^N)\n",
	   p->name,
	   (p->flags & FROGGED ? "in an infantile fashion " : ""),
	   str);
}

/* Silver did these 3 rather handy funtions :) */
/* Awwww, gee thanks :o) --Silver */

/* Main Channel */

void ppl_wall(char *str)
{
  player *scan;

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if (scan->residency && !(scan->misc_flags & NO_MAIN_CHANNEL) && scan->location)
    {
      if (scan->misc_flags & CHAN_HI)
      {
	command_type |= HIGHLIGHT;
      }
      sys_color_atm = UCOsc;
      tell_player(scan, str);
      sys_color_atm = SYSsc;
      if (scan->misc_flags & CHAN_HI)
      {
	command_type &= ~HIGHLIGHT;
      }
    }
  }
}

/* Spod channel */

void spod_wall(char *str)
{
  player *scan;

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if ((scan->residency & SPOD) && !(scan->misc_flags & NO_SPOD_CHANNEL) && scan->location)
    {
      if (scan->misc_flags & CHAN_HI)
      {
	command_type |= HIGHLIGHT;
      }
      sys_color_atm = UCEsc;
      tell_player(scan, str);
      sys_color_atm = SYSsc;
      if (scan->misc_flags & CHAN_HI)
      {
	command_type &= ~HIGHLIGHT;
      }
    }
  }
}

/* ZChannels */

void zwall(char *str)
{
  player *scan, *p = current_player;	/* blimey changed this */

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if (scan->residency && !strcasecmp(scan->zchannel, p->zchannel) && scan->location)
    {
      if (scan->misc_flags & CHAN_HI)
      {
	command_type |= HIGHLIGHT;
      }
      sys_color_atm = ZCHsc;
      tell_player(scan, str);
      scan->zcidle = 0;		/* reset that channels idle time */
      sys_color_atm = SYSsc;
      if (scan->misc_flags & CHAN_HI)
      {
	command_type &= ~HIGHLIGHT;
      }
    }
    else  /* if we get here, then they've got this set wrongly so */
      scan->misc_flags &=~ SEE_DEBUG_CHANNEL;  /* turn it off */
  }
}

/* A debugging one */

void debug_wall(char *str)
{
  player *scan;

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if (scan->residency & DEBUG)
    {
      if ((scan->misc_flags & SEE_DEBUG_CHANNEL) && scan->location)
      {
        if (scan->misc_flags & CHAN_HI)
        {
  	  command_type |= HIGHLIGHT;
        }
        TELLPLAYER(scan, "%s %s\n", get_config_msg("debug_chan"), str);
        if (scan->misc_flags & CHAN_HI)
        {
	  command_type &= ~HIGHLIGHT;
        }
      }
    }
  }
}

/*
 * blimey wrote this ....
 *
 */

void any_chan(char *prefix,
	      void (*the_wall) (char *),
	      char *format,
	      va_list ap)
{

  char *oldstack = stack;
  command_type = 0;

  sprintf(stack, "%s ", prefix);
  stack = strchr(stack, 0);

  vsprintf(stack, format, ap);
  stack = end_string(stack);

  the_wall(oldstack);
  stack = oldstack;
}


void au_chan(char *format,...)
{
  va_list x;
  va_start(x, format);
  any_chan(get_config_msg("admin_chan"), au_wall, format, x);
  va_end(x);
}
void cu_chan(char *format,...)
{
  va_list x;
  va_start(x, format);
  any_chan(get_config_msg("main_chan"), ppl_wall, format, x);
  va_end(x);
}

#ifdef HC_CHANNEL
void hu_chan(char *format,...)
{
  va_list x;
  va_start(x, format);
  any_chan(get_config_msg("hc_chan"), hc_wall, format, x);
  va_end(x);
}

#endif
void pu_chan(char *format,...)
{
  va_list x;
  va_start(x, format);
  any_chan(get_config_msg("spod_chan"), spod_wall, format, x);
  va_end(x);
}
void su_chan(char *format,...)
{
  va_list x;
  va_start(x, format);
  any_chan(get_config_msg("su_chan"), su_wall, format, x);
  va_end(x);
}
void zu_chan(char *format,...)
{
  va_list x;
  char *oldstack = stack;

  sprintf(stack, "<(%s)>", current_player->zchannel);
  stack += 1 + strlen(stack);
  va_start(x, format);
  any_chan(oldstack, zwall, format, x);
  va_end(x);

  stack = oldstack;
}

int got_msg(player * p, char *str, char *cname)
{

  if (!*str)
    TELLPLAYER(p, " Format: %s <message>\n", cname);
  return *str;
}

void toggle_debug_channel(player * p, char *str)
{
  if (p->misc_flags & SEE_DEBUG_CHANNEL)
  {
    p->misc_flags &= ~SEE_DEBUG_CHANNEL;
    tell_player(p, " You ignore the debug channel.\n");
  }
  else
  {
    p->misc_flags |= SEE_DEBUG_CHANNEL;
    tell_player(p, " You start viewing the debug channel.\n");
  }
}

void channel_toggle(player * p,
		    void (*the_wall) (char *,...),
		    int flag)
{

  if (p->misc_flags & flag)
  {
    p->misc_flags &= ~flag;
    the_wall("++ %s joins the channel ++\n", p->name);
#ifdef INTERCOM
    if (flag == NO_INTERCOM_CHANNEL)
      intercom_channel_action(p, "join");
#endif
  }
  else
  {
    the_wall("-- %s leaves the channel --\n", p->name);
    p->misc_flags |= flag;
#ifdef INTERCOM
    if (flag == NO_INTERCOM_CHANNEL)
      intercom_channel_action(p, "leave");
#endif
  }
}

int not_blocking_su_channel(player * p)
{
  if (!(p->flags & BLOCK_SU))
    return 1;
  tell_player(p, " You are off duty, so you can't use the channel.\n");
  return 0;
}

int is_on_channel(player * p, int flag)
{
  char *which = NULL;

  if (!(p->misc_flags & flag))
    return 1;

  switch (flag)
  {
    case NO_SPOD_CHANNEL:
      which = "spod";
      break;
    case NO_MAIN_CHANNEL:
      which = "main";
      break;
#ifdef INTERCOM
    case NO_INTERCOM_CHANNEL:
      which = "intercom";
      break;
#endif
      /* add in any more channels here ... */
  }
  TELLPLAYER(p, " You aren't on the %s channel!\n", which);
  return 0;
}

int is_on_zchannel(player * p)
{
  if (!p->zchannel[0])
    tell_player(p, " You aren't on any zchannel!\n");
  return p->zchannel[0];
}

/*
 * Actual channel command functions now follow -- blimey
 *
 */
void chanhi(player * p, char *str)
{
  TELLPLAYER(p, " Channels will no%c be hilited.\n",
	     (p->misc_flags ^= CHAN_HI) & CHAN_HI ? 'w' : 't');
}

/* toggle whether the su channel is highlighted or not */
void su_hilited(player * p, char *str)
{
  TELLPLAYER(p, " You will %sget the su channel hilited.\n",
	     (p->misc_flags ^= SU_HILITED) & SU_HILITED ? "" : "not ");
}

/*
 * Admin channel
 *
 */
void adminemote(player * p, char *str)
{
  if (got_msg(p, str, "ae") && not_blocking_su_channel(p))
    channel_emote(p, str, au_chan);
}
void adminsing(player * p, char *str)
{
  if (got_msg(p, str, "as") && not_blocking_su_channel(p))
    channel_sing(p, str, au_chan);
}
void adminthink(player * p, char *str)
{
  if (got_msg(p, str, "at") && not_blocking_su_channel(p))
    channel_think(p, str, au_chan);
}
void ad(player * p, char *str)
{
  if (got_msg(p, str, "au") && not_blocking_su_channel(p))
    channel_say(p, str, au_chan);
}
/*
 * Main channel
 *
 */
void ce(player * p, char *str)
{
  if (got_msg(p, str, "ce") && is_on_channel(p, NO_MAIN_CHANNEL))
    channel_emote(p, str, cu_chan);
}
void cs(player * p, char *str)
{
  if (got_msg(p, str, "cs") && is_on_channel(p, NO_MAIN_CHANNEL))
    channel_sing(p, str, cu_chan);
}
void ct(player * p, char *str)
{
  if (got_msg(p, str, "ct") && is_on_channel(p, NO_MAIN_CHANNEL))
    channel_think(p, str, cu_chan);
}
void cu(player * p, char *str)
{
  if (got_msg(p, str, "cu") && is_on_channel(p, NO_MAIN_CHANNEL))
    channel_say(p, str, cu_chan);
}
#ifdef HC_CHANNEL
/* HCAdmin channel - not one I particulary want but this was requested */
/* Bah! -- Silver */

/* Note - HC channel colour is the same as the admin channel colour. I could
   have given it a new colour BUT it would mean that PG+ was not directly
   compatable with PG pfiles (you would have had to run the pfiles through
   a convertor) so its a programming challenge for you to code it in! */
void he(player * p, char *str)
{
  if (got_msg(p, str, "he") && not_blocking_su_channel(p))
    channel_emote(p, str, hu_chan);
}
void hs(player * p, char *str)
{
  if (got_msg(p, str, "hs") && not_blocking_su_channel(p))
    channel_sing(p, str, hu_chan);
}
void ht(player * p, char *str)
{
  if (got_msg(p, str, "ht") && not_blocking_su_channel(p))
    channel_think(p, str, hu_chan);
}
void hd(player * p, char *str)
{
  if (got_msg(p, str, "hu") && not_blocking_su_channel(p))
    channel_say(p, str, hu_chan);
}
#endif
/*
 * Spod channel
 *
 */
void pe(player * p, char *str)
{
  if (got_msg(p, str, "pe") && is_on_channel(p, NO_SPOD_CHANNEL))
    channel_emote(p, str, pu_chan);
}
void ps(player * p, char *str)
{
  if (got_msg(p, str, "ps") && is_on_channel(p, NO_SPOD_CHANNEL))
    channel_sing(p, str, pu_chan);
}
void pt(player * p, char *str)
{
  if (got_msg(p, str, "pt") && is_on_channel(p, NO_SPOD_CHANNEL))
    channel_think(p, str, pu_chan);
}
void pu(player * p, char *str)
{
  if (got_msg(p, str, "pu") && is_on_channel(p, NO_SPOD_CHANNEL))
    channel_say(p, str, pu_chan);
}
/*
 * SU channel
 *
 */
void suemote(player * p, char *str)
{
  if (got_msg(p, str, "se") && not_blocking_su_channel(p))
    channel_emote(p, str, su_chan);
}
void susing(player * p, char *str)
{
  if (got_msg(p, str, "ss") && not_blocking_su_channel(p))
    channel_sing(p, str, su_chan);
}
void suthink(player * p, char *str)
{
  if (got_msg(p, str, "st") && not_blocking_su_channel(p))
    channel_think(p, str, su_chan);
}
void su(player * p, char *str)
{
  if (got_msg(p, str, "su") && not_blocking_su_channel(p))
    channel_say(p, str, su_chan);
}
/*
 * Z - Channels
 *
 */
void ze(player * p, char *str)
{
  if (got_msg(p, str, "ze") && is_on_zchannel(p))
    channel_emote(p, str, zu_chan);
}
void zs(player * p, char *str)
{
  if (got_msg(p, str, "zs") && is_on_zchannel(p))
    channel_sing(p, str, zu_chan);
}
void zt(player * p, char *str)
{
  if (got_msg(p, str, "zt") && is_on_zchannel(p))
    channel_think(p, str, zu_chan);
}
void zu(player * p, char *str)
{
  if (got_msg(p, str, "zu") && is_on_zchannel(p))
    channel_say(p, str, zu_chan);
}
/*
 * Rest of file is Silver's work
 *
 */

/* Thank you blimey and I present to you ... ZChannel stuff :o) */

void zc(player * p, char *str)
{
  char *oldstack = stack;
  char *check;
  player *scan;
  int newchan = 1;
  char chan_copy[20];

  if (!*str)
  {
    if (p->zchannel[0])
    {
      ENDSTACK("<(%s)> -- %s leaves this channel --\n", p->zchannel, p->name);
      zwall(oldstack);
      stack = oldstack;
      p->zchannel[0] = '\0';
    }
    else
      tell_player(p, " Format: zc <channel name to join or create>\n");
    return;
  }
  if (strlen(str) < 3 || strlen(str) > 14)
  {
    tell_player(p, "Z Channel names must be between 3 and 14 characters\n");
    return;
  }
  for (check = str; *check; check++)
  {
    switch (*check)
    {
      case '^':
	tell_player(p, " You may not have colours in your channel name.\n");
	return;
      case ' ':
	tell_player(p, " You may not have spaces in your channel name.\n");
	return;
      case ',':
	tell_player(p, " You may not have commas in your channel name.\n");
	return;
      case '{':
      case '}':
      case '*':
      case '<':
      case '>':
      case '[':
      case ']':
	TELLPLAYER(p, " You may not have %c in your channel name.\n", *check);
	return;
      case '(':
	tell_player(p, " You may not have brackets in your channel name.\n");
	return;
      case ')':
	tell_player(p, " You may not have brackets in your channel name.\n");
	return;
    }
  }

  if (!strcasecmp(str, p->zchannel))
  {
    tell_player(p, "Erm, you're already on that channel!\n");
    return;
  }
  /* Makes a copy of the channel name, converts it into lower case and
     does all the necessary checks. This means that ststr can pick up
     on reserved names and people don't moan becuase they
     can't use mixed case channel names -- Silver */

  strcpy(chan_copy, str);	/* copy it */
  lower_case(chan_copy);	/* convert it all to lower case */

  /* Here you need to enter the name of any channel names you DONT want
     people to use */

  if (strstr(chan_copy, "channel") || strstr(chan_copy, "spod") ||
      strstr(chan_copy, "admin") || strstr(chan_copy, "su"))
  {
    tell_player(p, " Sorry but that channel name is reserved.\n");
    return;
  }
  if (p->zchannel[0])
  {
    ENDSTACK("<(%s)> -- %s leaves this channel --\n", p->zchannel, p->name);
    zwall(oldstack);
    stack = oldstack;
  }
  for (scan = flatlist_start; scan; scan = scan->flat_next)
    if (!strcasecmp(scan->zchannel, str) && scan->location)
    {
      strcpy(p->zchannel, scan->zchannel);
      newchan = 0;
    }
  if (newchan == 1)
    strcpy(p->zchannel, str);

  if (newchan)
    ENDSTACK("<(%s)> ++ %s creates and joins this channel ++\n", p->zchannel, p->name);
  else
    ENDSTACK("<(%s)> ++ %s joins this channel ++\n", p->zchannel, p->name);

  zwall(oldstack);
  stack = oldstack;

  LOGF("channel", "%s creates a zchannel called '%s'", p->name, str);
}


void lsz(player * p, char *str)
{

  char *oldstack;
  player *scan, *scan2;
  int count = 0;
  int noz = 0;

  oldstack = stack;
  pstack_mid("Active Z-Channels");
  ADDSTACK("\nZ Channel Name                Number of people       Idle Time\n");

  for (scan = flatlist_start; scan; scan = scan->flat_next)
    scan->zchannellisted = 0;

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if (strlen(scan->zchannel) > 0 && scan->zchannellisted != 1)
    {
      count = 0;
      for (scan2 = flatlist_start; scan2; scan2 = scan2->flat_next)
      {
	if (!strcasecmp(scan2->zchannel, scan->zchannel))
	{
	  count++;
	  scan2->zchannellisted = 1;
	}
      }

      if (count > 0)
      {
	ADDSTACK("%-30s      %d               (%2d:%.2d idle)\n", scan->zchannel, count, scan->zcidle / 60, scan->zcidle % 60);
	noz++;
      }
    }
  }

  if (noz == 0)
  {
    tell_player(p, " There are no Z Channels currently active\n");
    stack = oldstack;
    return;
  }
  ENDSTACK("\n" LINE);

  tell_player(p, oldstack);
  stack = oldstack;
}

/* zw, cw and pw commands */

void z_who(player * p, char *str)
{
  char *oldstack = stack;
  char top[70];

  if (!is_on_zchannel(p))	/* blimey */
    return;

  sprintf(top, "People listening to zchannel '%s'", p->zchannel);
  pstack_mid(top);

  who_on_chan(p, 1);

  tell_player(p, oldstack);
  stack = oldstack;
}

void m_who(player * p, char *str)
{
  char *oldstack = stack;

  pstack_mid("People listening to the main channel");

  who_on_chan(p, 2);

  tell_player(p, oldstack);
  stack = oldstack;
}

void a_who(player * p, char *str)
{
  char *oldstack = stack;
  char midder[160];

  sprintf(midder, "People listening to the %s channel",
	  get_config_msg("admin_name"));

  pstack_mid(midder);

  who_on_chan(p, 3);

  tell_player(p, oldstack);
  stack = oldstack;
}

void s_who(player * p, char *str)
{
  char *oldstack = stack;
  char midder[160];

  sprintf(midder, "People listening to the %s channel",
	  get_config_msg("su_name"));

  pstack_mid(midder);

  who_on_chan(p, 4);

  tell_player(p, oldstack);
  stack = oldstack;
}

void p_who(player * p, char *str)
{
  char *oldstack = stack;

  pstack_mid("People listening to the spod channel");

  who_on_chan(p, 5);

  tell_player(p, oldstack);
  stack = oldstack;
}

#ifdef HC_CHANNEL
void h_who(player * p, char *str)
{
  char *oldstack = stack;
  char midder[160];

  sprintf(midder, "People listening to the %s channel",
	  get_config_msg("hc_name"));

  pstack_mid(midder);

  who_on_chan(p, 6);

  tell_player(p, oldstack);
  stack = oldstack;
}
#endif

void who_on_chan(player * p, int chan)
{
  player *scan;
  int flag = 0;

  sprintf(stack, "\n");
  stack = strchr(stack, 0);

  for (scan = flatlist_start; scan; scan = scan->flat_next)
  {
    if (scan->residency && scan->location)
    {
      flag = 0;

      if (chan == 1 && !strcasecmp(p->zchannel, scan->zchannel))
	flag = 1;

      if (chan == 2 && !(scan->misc_flags & NO_MAIN_CHANNEL))
	flag = 1;

      if (chan == 3 && !(scan->flags & BLOCK_SU) && (scan->residency & LOWER_ADMIN))
	flag = 1;

      if (chan == 4 && (!(scan->flags & BLOCK_SU)) && scan->residency & PSU)
	flag = 1;

      if (chan == 5 && (scan->residency & SPOD) && !(scan->misc_flags & NO_SPOD_CHANNEL))
	flag = 1;

#ifdef HC_CHANNEL
      if (chan == 6 && (!(scan->flags & BLOCK_SU)) && scan->residency & HCADMIN)
	flag = 1;
#endif

      if (flag)
      {
	sprintf(stack, "%s  ", scan->name);
	stack = strchr(stack, 0);
      }
    }
  }
  sprintf(stack, "\n\n"
	  LINE);
  stack = end_string(stack);
}

/* Superuser channel deletion */

void zdel(player * p, char *str)
{
  char *oldstack = stack;
  char *reason;
  player *scan;
  int found = 0;

  if (!(reason = strchr(str, ' ')))
  {
    tell_player(p, " Format: zdel <channel name> <reason>\n"
		"  Reason is logged and also sent to that channel!\n");
    return;
  }
  *reason++ = 0;
  for (scan = flatlist_start; scan; scan = scan->flat_next)
    if (!strcasecmp(scan->zchannel, str) && scan->location)
    {

      sprintf(stack, "<(%s)> -- %s is destroying this channel. Reason: %s --\n",
	      scan->zchannel, p->name, reason);
      stack = end_string(stack);

      if (scan->misc_flags & CHAN_HI)
	command_type |= HIGHLIGHT;
      sys_color_atm = UCEsc;
      tell_player(scan, oldstack);
      sys_color_atm = SYSsc;
      if (scan->misc_flags & CHAN_HI)
	command_type &= ~HIGHLIGHT;

      stack = oldstack;
      strcpy(scan->zchannel, "");
      found = 1;
    }
  if (found == 0)
  {
    tell_player(p, " That channel doesn't exist!\n");
    return;
  }
  SW_BUT(p, " -=*> %s destroys the '%s' channel for the reason: %s\n", p->name, str, reason);
  tell_player(p, " Channel destroyed and reason logged\n");
  LOGF("channel", "%s destroyed '%s'. Reason: %s", p->name, str, reason);
}

/* The muffle command */

void muffle(player * p, char *str)
{
  char *oldstack = stack;
  player *p2 = p;
  char title[70];

  if ((*str && p->residency & LOWER_ADMIN))
  {
    p2 = find_player_global_quiet(str);
    if (p2)
      *str = 0;
  }

  if (!*str)
  {
    if (p2 != p)
      sprintf(title, "Muffle information for %s", p2->name);
    else
      sprintf(title, "Muffle information");

    pstack_mid(title);
    ADDSTACK("\nMain channel                 ");
    if (p2->misc_flags & NO_MAIN_CHANNEL)
      ADDSTACK("<ignoring>\n");
    else
      ADDSTACK("<listening>\n");
#ifdef INTERCOM
    ADDSTACK("Intercom channel             ");
    if (p2->misc_flags & NO_INTERCOM_CHANNEL)
      ADDSTACK("<ignoring>\n");
    else
      ADDSTACK("<listening>\n");
#endif
    if (p2->residency & SPOD)
    {
      ADDSTACK("Spod channel                 ");
      if (p2->misc_flags & NO_SPOD_CHANNEL)
	ADDSTACK("<ignoring>\n");
      else
	ADDSTACK("<listening>\n");
    }
    ADDSTACK("Sessions                     ");
    if (p2->custom_flags & YES_SESSION)
      ADDSTACK("<off>\n");
    else
      ADDSTACK("<on>\n");
    ADDSTACK("Clock                        ");
    if (p2->custom_flags & NO_CLOCK)
      ADDSTACK("<off>\n");
    else
      ADDSTACK("<on>\n");
    ADDSTACK("Dynatext                     ");
    if (p2->custom_flags & NO_DYNATEXT)
      ADDSTACK("<ignoring>\n");
    else
      ADDSTACK("<seeing>\n");

    if (p2->residency & DEBUG)
    {
      ADDSTACK("Debug channel                ");
      if (p2->misc_flags & SEE_DEBUG_CHANNEL)
	ADDSTACK("<listening>\n");
      else
	ADDSTACK("<ignoring>\n");
    }

    ENDSTACK("\n" LINE);
    tell_player(p, oldstack);
    stack = oldstack;
    return;
  }
  if (strstr(str, "mai"))
    channel_toggle(p, cu_chan, NO_MAIN_CHANNEL);	/* blimey */
#ifdef INTERCOM
  else if (strstr(str, "int") || strstr(str, "ich"))
    channel_toggle(p, i_chan, NO_INTERCOM_CHANNEL);    /* Silver */
#endif
  else if (strstr(str, "spo") && p->residency & SPOD)
    channel_toggle(p, pu_chan, NO_SPOD_CHANNEL);	/* blimey */
  else if (strstr(str, "ses"))
    set_yes_session(p, "");
  else if (strstr(str, "clo"))
    toggle_view_clock(p, "");
  else if (strstr(str, "dyn"))
    toggle_yes_dynatext(p, "");
  else if (strstr(str, "deb") && p->residency & DEBUG)
    toggle_debug_channel(p, "");
  else
  {
    tell_player(p, " Format: muffle <section>\n"
		"  Where section can be: main");
    if (p->residency & SPOD)
      tell_player(p, ", spod");
    if (p->residency & DEBUG)
      tell_player(p, ", debug");
    tell_player(p, ", session, clock, dynatext\n");
  }
}

/* Version information */
void channel_version()
{
  sprintf(stack, " -=*> Channel code v2.0 (by Silver and blimey) installed.\n");
  stack = strchr(stack, 0);
}

#ifdef INTERCOM
#include "channel2.c"
#endif