musicmud-2.1.6/data/
musicmud-2.1.6/data/help/
musicmud-2.1.6/data/policy/
musicmud-2.1.6/data/wild/
musicmud-2.1.6/data/world/
musicmud-2.1.6/doc/
musicmud-2.1.6/src/ident/
musicmud-2.1.6/src/lua/
musicmud-2.1.6/src/lua/include/
musicmud-2.1.6/src/lua/src/lib/
musicmud-2.1.6/src/lua/src/lua/
musicmud-2.1.6/src/lua/src/luac/
/* 
 * MusicMUD - Minmissions Module
 * Copyright (C) 1998-2003 Abigail Brady
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 * 
 */

#include <set>
#include <list>

#include "musicmud.h"
#include "verbs.h"
#include "util.h"
#include "pflags.h"
#include "Mission.h"
#include "misc.h"
#include "hooks.h"
#include "trap.h"
#include "events.h"
#include "prep.h"
#include "shared.h"
#include "hooks.h"

#include "nations.h"

namespace minis {

#define ARRAY_SIZE(a) (sizeof(a)/(sizeof((a)[0])))

#define MODULE "minis"

//! Data about a minimission
struct mini_t
{
  string tag;
  int reward;
  const char *type;
  const char *zone;
  int flags;
  MudObject* obj;

  bool operator<(const mini_t &c) const {
    return strcmp(type, c.type)<0;
  }

  bool can() const {
    if (obj)
      return dotrap(E_ONMINICAN, obj, obj);
    /* ::: minican o1==the minimission template; return 1 to indicate that a minimission of this type can be created at the moment */
    return 0;
  }

  void init(Mission *o) const {
    if (obj) {
      dotrap(E_ONMINICREATE, obj, obj, o);
    /* ::: minicreate o1==the minimission template, o2==the minimission; set up an instance of this minimission using o2 */
      return;
    }
  }
};

mini_t make_mini(MudObject *from) {
  mini_t m;
  if (const char *c=from->get("minitag"))
    m.tag = c;
  else
    m.tag = ssprintf("Quest%i", from->get_int("miniid")+32);
  m.reward = from->get_int("reward");
  m.type = from->get("mname");
  m.zone = from->get("mzone");
  m.flags = from->get_flag(FL_PRIVATE);
  m.obj = from;
  return m;
}

static const char *niceboard(const char *q) {
  if (streq(q, "*") || !q) return "anywhere";
  MudObject *z = getzone(q);
  if (z)
    return get_zoneprop(z, "planet", "somewhere");
  return "somewhere";
}

set<mini_t> get_minis(int p=1) {
  set<mini_t> minis;
  if (MudObject*m=planet->get("mini_zone")) {
    MudObject *o;
    int i;
    foreach(m->children, o, i) {
      if (o->get_object("start")!=m)
	continue;
      mini_t m = make_mini(o);
      if (p || !(m.flags&1))
	minis.insert(m);
    }
  }

  return minis;
}

int count_minis() {
  return get_minis(0).size();
}

int done_minis(const MudObject *o) {
  set<mini_t> m = get_minis(0);
  int y =0;
  for (set<mini_t>::iterator i=m.begin();i!=m.end();i++) {
    if (quest_done(o, i->tag)) {
      y++;
    }
  }
  return y;
}

static bool mini_lookup(const char *name, mini_t *min)
{
  set<mini_t> m = get_minis();
  for (set<mini_t>::iterator i=m.begin();i!=m.end();i++) {
    if (streq(i->type, name)) {
      *min = *i;
      return 1;
    }
  }
  return 0;
}

static bool verb_minis(MudObject *who, int argc, const char **argv) {
  MudObject *whose = who;

  if (argc > 1) {
    whose = get_player(who, argv[1]);

    if (!whose) {
      who->printf("Can't find : %s.\n", argv[1]);
      return true;
    }

    if (whose != who && !who->get_priv(PFL_SEESTATS)) {
      who->printf("You cannot do that on others.\n");
      return true;
    }

    if (is_mobile(whose)) {
      who->printf("%#M is a mobile, and is too lazy to do missions.\n", whose);
      return true;
    }
  }

  set<mini_t> minis = get_minis();
  set<mini_t>::iterator mi = minis.begin();

  list<Mission*> missions;

  MudObject *o;
  int i;
  foreach(planet, o, i) 
    if (Mission *m=dynamic_cast<Mission*>(o))
      missions.push_back(m);

  if (who->get_priv(PFL_MINIMISSIONS)) {
    who->printf("%-15s %-12s %-12s %5s %7s   %s %s\n", "ID", "Type", "Board", "Count", "Reward", "Done ", "Can?");
    who->printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-\n");
    while (mi != minis.end()) {
      int count = 0;
      for (list<Mission*>::iterator mit = missions.begin();mit!=missions.end();mit++) {
      	if ((*mit)->get_object("instance")==mi->obj) {
      	  count++;
      	}
      }

      who->printf("%-15s %-12s %-12s %3i   %7s   %s%s %s\n",
		  mi->obj->id,
		  mi->type,
		  niceboard(mi->zone),
		  count++,
		  formatvalue(mi->reward, currency(who), 0),
		  quest_done(whose, mi->tag)?"done  ":"      ",
		  mi->can()?"yes ":"no  ",
		  (mi->flags & 1)?"(^rNot open^n)":"");		  

      mi++;      
    }
    return true;
  }

  who->printf(" %-12s %-12s %7s   %s\n", "Type", "Board", "Reward", "Done ");
  who->printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-\n");
  while (mi != minis.end()) {
    if (mi->flags & 1) {
      mi++;
      continue;
    }

    who->printf(" %-12s %-12s %6s   %s\n", 
		mi->type,
		niceboard(mi->zone),
		formatvalue(mi->reward, currency(who), 0),
		quest_done(whose, mi->tag)?"done  ":"      ");
    mi++;
  }

  return true;
}


static Mission *allocate(MudObject *who, MudObject *board, mini_t *mini) {
  mini_t mymini;
  set<mini_t> minis = get_minis();

  if (!mini) {
    set<mini_t> possibles;
    set<mini_t>::iterator it = minis.begin();
    while (it != minis.end()) {
      if (it->flags & 1) {
	it++;
	continue;
      }
      
      if (it->can())
	possibles.insert(*it);
      it++;
    }
    
    it = possibles.begin();
    while (it != possibles.end()) {
      it++;
    }
    if (possibles.empty())
      return 0;
    int n = random_number(possibles.size());
    it = possibles.begin();
    while (n) {
      it++;
      n--;
    }
    mymini = *it;
    mini = &mymini;
  }

  if (!mini->can()) {
    who->printf("Can't allocate a minimission of that type.\n");
    return 0;
  }
  
  Mission *m = new Mission(get_clone_name().c_str());
  planet->add(*m);
  
  m->set("mass", 50);
  m->set("short", "mission");
  m->set("name", "a ^omission^n");
  m->set_flag(FL_DESTROYONRESET, 1);
  m->set("minitag", mini->tag);
  m->set("deadline", now);
  m->set("treatas","mini_ticktock_1");
  
  m->set("reward", mini->reward);
  m->set("type", mini->type);
  m->set("bzone", mini->zone);

  if (mini->obj)
    m->set("instance", mini->obj->id);

  set_owner(m, board);
  
  mini->init(m);

  if (!m->get("desc")) {
    who->printf("It didn't stick. Destroying.\n");
    set_owner(m, mud);
    m->nuke_me = 1;
    return 0;
  }
  
  return m;
}

static bool verb_mmadd(MudObject *who, int argc, const char **argv) {
    if (who->get_flag(FL_SLEEPING)) {
        who->printf("You toss and turn in your sleep.\n");
        who->oprintf(cansee, "%#M tosses and turns in %s sleep.\n",who, his_or_her(who));
        return true;
    }
  MudObject *board = get_flagged_object(who->owner, FL_MISSIONSBOARD);
  if (!board) {
    who->printf("No board here.\n");
    return true;
  }

  if (MudObject *b=board->get_object("board")) {
    board = b;
  }

  who->interpret("mmtimeout");

  mini_t m;
  mini_t *pm = 0;

  if (argc > 1) {
    if (!mini_lookup(argv[1], &m)) {
      who->printf("Unknown mini type.\n");
      return true;
    }
    pm = &m;
  }

  if (board->children->getsize()>board->get_int("max", 4) && !pm) {
    who->printf("Board full.\n");
    return true;
  }

  if (Mission *mis=allocate(who, board, pm)) {
    who->interpret("emote places a notice on the ^omissions^n board.");
    who->printf("The briefing is: \n%s\n", mis->get("desc"));
  }

  return true;
}

}

using namespace minis;

#define CLEANUP COUNT_MINIS = 0; DONE_MINIS = 0;

#include "verbmodule.h"

void startup() {

  COUNT_MINIS = count_minis;
  DONE_MINIS = done_minis;

AUTO_VERB(mmadd, 5, 0, PFL_MINIMISSIONS);
AUTO_VERB(minis, 5, 0, PFL_NONE);

}