skylib_fluffos_v3/
skylib_fluffos_v3/bin/
skylib_fluffos_v3/bin/db/
skylib_fluffos_v3/fluffos-2.9-ds2.04/
skylib_fluffos_v3/fluffos-2.9-ds2.04/ChangeLog.old/
skylib_fluffos_v3/fluffos-2.9-ds2.04/Win32/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/
skylib_fluffos_v3/fluffos-2.9-ds2.04/compat/simuls/
skylib_fluffos_v3/fluffos-2.9-ds2.04/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/clone/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/command/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/data/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/etc/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/include/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/inherit/master/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/log/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/compiler/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/efuns/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/single/tests/operators/
skylib_fluffos_v3/fluffos-2.9-ds2.04/testsuite/u/
skylib_fluffos_v3/fluffos-2.9-ds2.04/tmp/
skylib_fluffos_v3/fluffos-2.9-ds2.04/windows/
skylib_fluffos_v3/mudlib/
skylib_fluffos_v3/mudlib/cmds/
skylib_fluffos_v3/mudlib/cmds/admin/
skylib_fluffos_v3/mudlib/cmds/guild-race/
skylib_fluffos_v3/mudlib/cmds/living/broken/
skylib_fluffos_v3/mudlib/cmds/player/group_cmds/
skylib_fluffos_v3/mudlib/cmds/playtester/
skylib_fluffos_v3/mudlib/d/admin/
skylib_fluffos_v3/mudlib/d/admin/room/
skylib_fluffos_v3/mudlib/d/admin/room/we_care/
skylib_fluffos_v3/mudlib/d/admin/save/
skylib_fluffos_v3/mudlib/d/admin/text/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/buildings/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/map/
skylib_fluffos_v3/mudlib/d/learning/TinyTown/roads/
skylib_fluffos_v3/mudlib/d/learning/chars/
skylib_fluffos_v3/mudlib/d/learning/functions/
skylib_fluffos_v3/mudlib/d/learning/handlers/
skylib_fluffos_v3/mudlib/d/learning/help_topics/
skylib_fluffos_v3/mudlib/d/learning/help_topics/npcs/
skylib_fluffos_v3/mudlib/d/learning/help_topics/objects/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rcs_demo/RCS/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/crowd/
skylib_fluffos_v3/mudlib/d/learning/help_topics/rooms/situations/
skylib_fluffos_v3/mudlib/d/learning/save/
skylib_fluffos_v3/mudlib/d/learning/school/
skylib_fluffos_v3/mudlib/d/learning/school/add_sc/
skylib_fluffos_v3/mudlib/d/learning/school/characters/
skylib_fluffos_v3/mudlib/d/learning/school/general/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/basic_commands/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/edtutor/
skylib_fluffos_v3/mudlib/d/learning/school/getting-started/unix_tutor/
skylib_fluffos_v3/mudlib/d/learning/school/items/
skylib_fluffos_v3/mudlib/d/learning/school/npc_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/room_basic/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/situations/
skylib_fluffos_v3/mudlib/d/learning/school/room_school/terrain_tutor/
skylib_fluffos_v3/mudlib/d/learning/text/
skylib_fluffos_v3/mudlib/d/liaison/
skylib_fluffos_v3/mudlib/d/mudlib/
skylib_fluffos_v3/mudlib/d/mudlib/changes/
skylib_fluffos_v3/mudlib/d/playtesters/
skylib_fluffos_v3/mudlib/d/playtesters/effects/
skylib_fluffos_v3/mudlib/d/playtesters/handlers/
skylib_fluffos_v3/mudlib/d/playtesters/items/
skylib_fluffos_v3/mudlib/d/sage/
skylib_fluffos_v3/mudlib/doc/
skylib_fluffos_v3/mudlib/doc/creator/
skylib_fluffos_v3/mudlib/doc/driver/
skylib_fluffos_v3/mudlib/doc/driver/efuns/arrays/
skylib_fluffos_v3/mudlib/doc/driver/efuns/buffers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/calls/
skylib_fluffos_v3/mudlib/doc/driver/efuns/compile/
skylib_fluffos_v3/mudlib/doc/driver/efuns/filesystem/
skylib_fluffos_v3/mudlib/doc/driver/efuns/floats/
skylib_fluffos_v3/mudlib/doc/driver/efuns/functions/
skylib_fluffos_v3/mudlib/doc/driver/efuns/general/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mappings/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mixed/
skylib_fluffos_v3/mudlib/doc/driver/efuns/mudlib/
skylib_fluffos_v3/mudlib/doc/driver/efuns/numbers/
skylib_fluffos_v3/mudlib/doc/driver/efuns/parsing/
skylib_fluffos_v3/mudlib/doc/login/
skylib_fluffos_v3/mudlib/doc/lpc/basic_manual/
skylib_fluffos_v3/mudlib/doc/lpc/intermediate/
skylib_fluffos_v3/mudlib/doc/new/add_command/
skylib_fluffos_v3/mudlib/doc/new/events/
skylib_fluffos_v3/mudlib/doc/new/handlers/
skylib_fluffos_v3/mudlib/doc/new/living/race/
skylib_fluffos_v3/mudlib/doc/new/living/spells/
skylib_fluffos_v3/mudlib/doc/new/object/
skylib_fluffos_v3/mudlib/doc/new/player/
skylib_fluffos_v3/mudlib/doc/new/room/guild/
skylib_fluffos_v3/mudlib/doc/new/room/outside/
skylib_fluffos_v3/mudlib/doc/new/room/storeroom/
skylib_fluffos_v3/mudlib/doc/object/
skylib_fluffos_v3/mudlib/doc/playtesters/
skylib_fluffos_v3/mudlib/doc/policy/
skylib_fluffos_v3/mudlib/doc/weapons/
skylib_fluffos_v3/mudlib/global/
skylib_fluffos_v3/mudlib/global/creator/
skylib_fluffos_v3/mudlib/handlers/
skylib_fluffos_v3/mudlib/include/casino/
skylib_fluffos_v3/mudlib/include/cmds/
skylib_fluffos_v3/mudlib/include/effects/
skylib_fluffos_v3/mudlib/include/npc/
skylib_fluffos_v3/mudlib/include/room/
skylib_fluffos_v3/mudlib/include/shops/
skylib_fluffos_v3/mudlib/net/daemon/
skylib_fluffos_v3/mudlib/net/daemon/chars/
skylib_fluffos_v3/mudlib/net/inherit/
skylib_fluffos_v3/mudlib/net/obj/
skylib_fluffos_v3/mudlib/net/obj/BACKUPS/
skylib_fluffos_v3/mudlib/obj/amulets/
skylib_fluffos_v3/mudlib/obj/armours/plate/
skylib_fluffos_v3/mudlib/obj/b_day/
skylib_fluffos_v3/mudlib/obj/clothes/transport/horse/
skylib_fluffos_v3/mudlib/obj/faith/symbols/
skylib_fluffos_v3/mudlib/obj/fungi/
skylib_fluffos_v3/mudlib/obj/gatherables/
skylib_fluffos_v3/mudlib/obj/instruments/
skylib_fluffos_v3/mudlib/obj/media/
skylib_fluffos_v3/mudlib/obj/misc/player_shop/
skylib_fluffos_v3/mudlib/obj/monster/godmother/
skylib_fluffos_v3/mudlib/obj/monster/transport/
skylib_fluffos_v3/mudlib/obj/rings/
skylib_fluffos_v3/mudlib/obj/scabbards/
skylib_fluffos_v3/mudlib/obj/spells/
skylib_fluffos_v3/mudlib/obj/stationery/
skylib_fluffos_v3/mudlib/obj/stationery/envelopes/
skylib_fluffos_v3/mudlib/obj/toys/
skylib_fluffos_v3/mudlib/obj/vessels/
skylib_fluffos_v3/mudlib/obj/weapons/axes/
skylib_fluffos_v3/mudlib/obj/weapons/chains/
skylib_fluffos_v3/mudlib/obj/weapons/maces/BACKUPS/
skylib_fluffos_v3/mudlib/save/autodoc/
skylib_fluffos_v3/mudlib/save/book_handler/
skylib_fluffos_v3/mudlib/save/books/history/calarien/
skylib_fluffos_v3/mudlib/save/mail/
skylib_fluffos_v3/mudlib/save/new_soul/data/
skylib_fluffos_v3/mudlib/save/parcels/
skylib_fluffos_v3/mudlib/save/playerinfo/
skylib_fluffos_v3/mudlib/save/players/d/
skylib_fluffos_v3/mudlib/save/players/s/
skylib_fluffos_v3/mudlib/save/random_names/
skylib_fluffos_v3/mudlib/save/random_names/data/
skylib_fluffos_v3/mudlib/save/terrains/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_desert/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_grassy_field/
skylib_fluffos_v3/mudlib/save/terrains/tutorial_mountain/
skylib_fluffos_v3/mudlib/save/todo_lists/
skylib_fluffos_v3/mudlib/secure/
skylib_fluffos_v3/mudlib/secure/cmds/admin/
skylib_fluffos_v3/mudlib/secure/cmds/lord/
skylib_fluffos_v3/mudlib/secure/config/
skylib_fluffos_v3/mudlib/secure/handlers/autodoc/
skylib_fluffos_v3/mudlib/secure/handlers/intermud/
skylib_fluffos_v3/mudlib/secure/include/global/
skylib_fluffos_v3/mudlib/secure/save/
skylib_fluffos_v3/mudlib/secure/save/handlers/
skylib_fluffos_v3/mudlib/secure/std/
skylib_fluffos_v3/mudlib/secure/std/classes/
skylib_fluffos_v3/mudlib/secure/std/modules/
skylib_fluffos_v3/mudlib/std/creator/
skylib_fluffos_v3/mudlib/std/dom/
skylib_fluffos_v3/mudlib/std/effects/
skylib_fluffos_v3/mudlib/std/effects/external/
skylib_fluffos_v3/mudlib/std/effects/fighting/
skylib_fluffos_v3/mudlib/std/effects/magic/
skylib_fluffos_v3/mudlib/std/effects/magic/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/other/BACKUPS/
skylib_fluffos_v3/mudlib/std/effects/priest/
skylib_fluffos_v3/mudlib/std/effects/room/
skylib_fluffos_v3/mudlib/std/environ/
skylib_fluffos_v3/mudlib/std/guilds/
skylib_fluffos_v3/mudlib/std/guilds/old/
skylib_fluffos_v3/mudlib/std/languages/
skylib_fluffos_v3/mudlib/std/liquids/
skylib_fluffos_v3/mudlib/std/npc/
skylib_fluffos_v3/mudlib/std/npc/goals/
skylib_fluffos_v3/mudlib/std/npc/goals/basic/
skylib_fluffos_v3/mudlib/std/npc/goals/misc/
skylib_fluffos_v3/mudlib/std/npc/plans/
skylib_fluffos_v3/mudlib/std/npc/plans/basic/
skylib_fluffos_v3/mudlib/std/npc/types/
skylib_fluffos_v3/mudlib/std/npc/types/helper/
skylib_fluffos_v3/mudlib/std/npcs/
skylib_fluffos_v3/mudlib/std/outsides/
skylib_fluffos_v3/mudlib/std/races/shadows/
skylib_fluffos_v3/mudlib/std/room/basic/BACKUPS/
skylib_fluffos_v3/mudlib/std/room/basic/topography/
skylib_fluffos_v3/mudlib/std/room/controller/
skylib_fluffos_v3/mudlib/std/room/inherit/topography/
skylib_fluffos_v3/mudlib/std/room/topography/area/
skylib_fluffos_v3/mudlib/std/room/topography/iroom/
skylib_fluffos_v3/mudlib/std/room/topography/milestone/
skylib_fluffos_v3/mudlib/std/shadows/curses/
skylib_fluffos_v3/mudlib/std/shadows/disease/
skylib_fluffos_v3/mudlib/std/shadows/fighting/
skylib_fluffos_v3/mudlib/std/shadows/healing/
skylib_fluffos_v3/mudlib/std/shadows/magic/
skylib_fluffos_v3/mudlib/std/shadows/poison/
skylib_fluffos_v3/mudlib/std/shadows/room/
skylib_fluffos_v3/mudlib/std/shops/controllers/
skylib_fluffos_v3/mudlib/std/shops/objs/
skylib_fluffos_v3/mudlib/std/shops/player_shop/
skylib_fluffos_v3/mudlib/std/socket/
skylib_fluffos_v3/mudlib/std/soul/d/
skylib_fluffos_v3/mudlib/std/soul/e/
skylib_fluffos_v3/mudlib/std/soul/i/
skylib_fluffos_v3/mudlib/std/soul/j/
skylib_fluffos_v3/mudlib/std/soul/k/
skylib_fluffos_v3/mudlib/std/soul/l/
skylib_fluffos_v3/mudlib/std/soul/n/
skylib_fluffos_v3/mudlib/std/soul/o/
skylib_fluffos_v3/mudlib/std/soul/q/
skylib_fluffos_v3/mudlib/std/soul/r/
skylib_fluffos_v3/mudlib/std/soul/u/
skylib_fluffos_v3/mudlib/std/soul/v/
skylib_fluffos_v3/mudlib/std/soul/y/
skylib_fluffos_v3/mudlib/std/soul/z/
skylib_fluffos_v3/mudlib/std/stationery/
skylib_fluffos_v3/mudlib/w/
skylib_fluffos_v3/mudlib/w/default/
skylib_fluffos_v3/mudlib/w/default/armour/
skylib_fluffos_v3/mudlib/w/default/clothes/
skylib_fluffos_v3/mudlib/w/default/item/
skylib_fluffos_v3/mudlib/w/default/npc/
skylib_fluffos_v3/mudlib/w/default/room/
skylib_fluffos_v3/mudlib/w/default/weapon/
skylib_fluffos_v3/mudlib/www/
skylib_fluffos_v3/mudlib/www/java/
skylib_fluffos_v3/mudlib/www/secure/
skylib_fluffos_v3/mudlib/www/secure/lpc/advanced/
skylib_fluffos_v3/mudlib/www/secure/lpc/intermediate/
skylib_fluffos_v3/win32/
/**
 * Todo command for all cres, editable by lords.
 * @author Windy, March 2001.
 * @change Rewritten almost completely by Avelan, May 2002.
 */

#include <colors.h>

#define SAVEFILE "/save/todo_lists/cretodo.o"
#define MAX_DAYS 60

class todo_item {
    string taskname;
    string person;
    int priority;
    int time;
    int due;
    string description;
    string assignedby;
}

class completed_item {
    string taskname;
    string person;
    int time;
    string description;
}

mapping completed, tasks;

/** @ignore yes */
private void save_me() {
    unguarded( (: save_object, SAVEFILE :) );
} /* save_me() */

/** @ignore yes */
private void load_me() {
    if( file_size(SAVEFILE) > 0 )
        unguarded( (: restore_object, SAVEFILE :) );
} /* load_me() */

/** @ignore yes */
void create() {
    load_me();
    if( !mapp(tasks) )
        tasks = ([ ]);
    if( !mapp(completed) )
        completed = ([ ]);
} /* create() */

/** @ignore yes */
string get_priority( int num ) {
    if( num )
        switch( num ) {
            case 1: return "Very High";
            case 2: return "High";
            case 3: return "Normal";
            case 4: return "Low";
            case 5: return "Very Low";
        }
} /* get_priority() */

/** @ignore yes */
int check_valid_list( string list_name ) {
    if( member_array( list_name, keys(tasks) ) != -1 )
        return 1;
    return 0;
} /* check_valid_list() */

/** @ignore yes */
int check_valid_task( string task_name, string list_name ) {
    if( !sizeof(tasks[list_name]) )
        return 0;

    foreach( class todo_item item in tasks[list_name] )
        if( item->taskname == task_name )
            return 1;

    return 0;

} /* check_valid_task() */

/** @ignore yes */
int create_list( string list_name ) {
    if( !lordp(TP) ) {
        add_failed_mess("Sorry, only lords and above may create new "
            "lists.\n");
        return 0;
    }

    if( !list_name || list_name == "" ) {
        add_failed_mess("No list name defined.\n");
        return 0;
    }

    list_name = lower_case(list_name);

    if( check_valid_list( list_name ) ) {
        add_failed_mess("A list called "+CAP(list_name)+" already exists.\n");
        return 0;
    }

    tasks[list_name] = ({ });
    completed[list_name] = ({ });
    save_me();

    write("Created "+CAP(list_name)+" todo list.\n");
    return 1;

} /* create_list() */

/** @ignore yes */
int remove_list( string list_name ) {
    if( !adminp(TP) ) {
        add_failed_mess("Sorry, only the admin can remove todo lists.\n");
        return 0;
    }

    list_name = lower_case(list_name);

    if( !check_valid_list(list_name) ) {
        add_failed_mess("A list called "+CAP(list_name)+" doesn't exist.\n");
        return 0;
    }

    map_delete( tasks, list_name );

    if( !sizeof( completed[list_name] ) )
        map_delete( completed, list_name );

    save_me();

    tell_object( TP, "Removed the "+CAP(list_name)+" list.\n");
    return 1;

} /* remove_list() */

/** @ignore yes */
int remove_task( string task_name, string list_name ) {
    if( !lordp(TP) ) {
        add_failed_mess("Sorry, only lords and above may remove tasks.\n");
        return 0;
    }

    list_name = lower_case(list_name);

    if( !check_valid_list(list_name) ) {
        add_failed_mess("A list called "+CAP(list_name)+" doesn't exist.\n");
        return 0;
    }

    task_name = lower_case(task_name);

    if( !check_valid_task( task_name, list_name ) ) {
        add_failed_mess("There is no task called "+CAP(task_name)+
            " on the "+CAP(list_name)+" list.\n");
        return 0;
    }

    foreach( class todo_item item in tasks[list_name] ) {
        if( item->taskname == task_name ) {
            tasks[list_name] -= ({ item });
            break;
        }
    }

    save_me();

    tell_object( TP, "Removed the task called "+CAP(task_name)+" from the "+
        CAP(list_name)+" list.\n");
    return 1;

} /* remove_task() */

/** @ignore yes */
int complete_task( string task_name, string list_name ) {
    if( !lordp(TP) ) {
        add_failed_mess("Sorry, only lords and above may mark tasks as "
            "completed.\n");
        return 0;
    }

    list_name = lower_case(list_name);

    if( !check_valid_list( list_name ) ) {
        add_failed_mess("A list called "+CAP(list_name)+" doesn't exist.\n");
        return 0;
    }

    task_name = lower_case(task_name);

    if( !check_valid_task( task_name, list_name ) ) {
        add_failed_mess("There is no task called "+CAP(task_name)+" on the "+
            CAP(list_name)+" list.\n");
        return 0;
    }

    foreach( class todo_item item in tasks[list_name] ) {
        if( item->taskname == task_name ) {
            completed[list_name] += ({ new( class completed_item,
                taskname : task_name,
                person : item->person,
                time : time(),
                description : item->description ) });
            tasks[list_name] -= ({ item });
        }
    }

    save_me();

    tell_object( TP, "Marked the task called "+CAP(task_name)+" as completed "
        "on the "+CAP(list_name)+" list.\n");
    return 1;

} /* complete_task() */

/** @ignore yes */
int disp_lists() {
    string ret;

    if( !sizeof(keys(tasks)) ) {
        add_failed_mess("No lists available.\n");
        return 0;
    }

    ret = "Todo lists for creators:\n\n"+
        implode( map( sort_array( keys(tasks), 1 ), (: "\t"+CAP($1) :) ),
            "\n")+"\n\nTotal lists: "+sizeof(keys(tasks))+"\n";

    TP->more_string(ret);
    return 1;

} /* disp_lists() */

/** @ignore yes */
string print_completed( int cols, string list, class completed_item item ) {
    return "List        : "+CAP(list)+"\n"
           "Task        : "+CAP(item->taskname)+"\n"
           "Completed   : "+ctime(item->time)+"\n"
           "Description :\n"+indent( item->description, 14, cols )+"\n\n";
} /* print_completed() */

/** @ignore yes */
int list_completed( string person ) {
    string ret, list;
    int amt, cols;
    class completed_item item;

    if( !person || person == "" ) {
        add_failed_mess("Who do you want to list the completed tasks for?\n");
        return 0;
    }

    person = lower_case(person);

    if( !rank(person) ) {
        add_failed_mess("There is no such player - "+CAP(person)+".\n");
        return 0;
    }

    if( !sizeof(keys(completed) ) ) {
        add_failed_mess("There are no completed tasks on any list.\n");
        return 0;
    }

    cols = (int)TP->query_cols();
    ret = sprintf("%s completed the following tasks:\n%|*'-'s\n",
        CAP( person == TP->query_name() ? "You have" : person+" has"),
        cols-1, "");

    foreach( list in keys(completed) ) {
        foreach( item in completed[list] ) {
            if( item->person == person ) {
                ret += print_completed( cols, list, item );
                ret += sprintf("%|*'-'s\n", cols-1, "");
                amt++;
            }
        }
    }

    if( !amt ) {
        write( ( person == TP->query_name() ? "You have" :
        CAP(person)+" has")+" not completed any tasks.\n");
        return 1;
    }

    ret += "Total completed : "+amt+"\n";
    TP->more_string(ret);
    return 1;

} /* list_completed() */

/** @ignore yes */
string print_task( int cols, string list, class todo_item item ) {
    return "List        : "+CAP(list)+"\n"
           "Task        : "+CAP(item->taskname)+"\n"
           "Assigned by : "+ctime(item->time)+" by "+CAP(item->assignedby)+"\n"
           "Assigned to : "+CAP(item->person)+"\n"
           "Priority    : "+get_priority(item->priority)+"\n"
           "Due on      : "+ctime(item->due)+( item->due > time() ? "" :
                          "(NOT COMPLETED IN TIME)")+"\n"
           "Description : "+indent( item->description, 14, cols )[14..]+"\n";
} /* print_task() */

/** @ignore yes */
int disp_list( string list_name ) {
    string ret;
    int amt, cols;

    list_name = lower_case(list_name);

    if( !check_valid_list(list_name) ) {
        add_failed_mess("A list called "+CAP(list_name)+" doesn't exist.\n");
        return 0;
    }

    if( !sizeof(tasks[list_name] ) ) {
        add_failed_mess("The "+CAP(list_name)+" list doesn't contain any "
            "tasks.\n");
        return 0;
    }

    cols = (int)TP->query_cols();
    ret = sprintf("%s todo list:\n%|*'-'s\n", CAP(list_name), cols-1, "");

    foreach( class todo_item item in tasks[list_name] ) {
        ret += print_task( cols, list_name, item );
        ret += sprintf("%|*'-'s\n", cols-1, "");
        amt++;
    }

    ret += "Total tasks : "+amt+"\n";
    TP->more_string(ret);
    return 1;

} /* disp_list() */

/** @ignore yes */
int disp_tasks( string person ) {
    string ret, list;
    int amt, cols;
    class todo_item item;

    if( !person || person == "" ) {
        add_failed_mess("Who do you want to list the tasks for?\n");
        return 0;
    }

    person = lower_case(person);

    if( !rank(person) ) {
        add_failed_mess("There is no such player - "+CAP(person)+".\n");
        return 0;
    }

    if( !sizeof(keys(tasks) ) ) {
        add_failed_mess("There are no active tasks on any list.\n");
        return 0;
    }

    cols = (int)TP->query_cols();
    ret = sprintf("The following tasks have been assigned to %s:\n%|*'-'s\n",
        ( person == TP->query_name() ? "you" : CAP(person) ), cols-1, "");

    foreach( list in keys(tasks) ) {
        foreach( item in tasks[list] ) {
            if( item->person == person ) {
                ret += print_task( cols, list, item );
                ret += sprintf("%|*'-'s\n", cols-1, "");
                amt++;
            }
        }
    }

    if( !amt ) {
        write("No tasks have been assigned to "+( person == TP->query_name() ?
            "you" : CAP(person) )+".\n");
        return 1;
    }

    ret += "Total tasks : "+amt+"\n";
    TP->more_string(ret);
    return 1;

} /* disp_tasks() */

/** @ignore yes */
private void add_list_item( string list, class todo_item item ) {

    tasks[list] += ({ item });

    tell_object( TP, "Added a task called "+CAP(item->taskname)+" to the "+
        CAP(list)+" list.\n");

    if( item->person != TP->query_name() ) {
        TCRE( item->person, GREEN+TP->query_cap_name()+" assigned you a task "
            "called "+CAP(item->taskname)+" on the "+CAP(list)+" list."+
            RESET+"\n");
    }

    save_me();

} /* add_list_item() */

/** @ignore yes */
void finish_add_task( string str, mixed data ) {
    class todo_item item;
    string list;

    if( !lordp(TP) ) {
        tell_object( TP, "Sorry, only lords and above may add tasks.\n");
        return;
    }

    if( !str || str == "" ) {
        tell_object( TP, "No task description.  Aborting...\n");
        return;
    }

    list = data[0];
    item = data[1];

    if( !list || list == "" || !classp(item) ) {
        tell_object( TP, "Oops, something has gone wrong.  Aborting...\n");
        return;
    }

    item->assignedby = TP->query_name();
    item->description = str;
    return add_list_item( list, item );

} /* finish_add_task() */

/** @ignore yes */
private void set_deadline( mixed due, string list, class todo_item item ) {
    if( due == "q" || due == "Q" ) {
        tell_object( TP, "Aborting...\n");
        return;
    }

    due = to_int(due);

    if( due < 1 || due > MAX_DAYS ) {
        tell_object( TP, "The deadline of the task must be between 1 and "+
            MAX_DAYS+".\n] ");
        input_to( (: set_deadline :), list, item );
        return;
    }

    item->time = time();
    item->due = time() + ( due * 24 * 60 * 60 );
    item->description = "";

    tell_object( TP, "Please edit the description of the task.\n");
    TP->do_edit( 0, (: finish_add_task :), 0, 0, ({ list, item }) );

} /* set_deadline() */

/** @ignore yes */
private void set_priority( mixed priority, string list, class todo_item item ) {
    if( priority == "q" || priority == "Q" ) {
        tell_object( TP, "Aborting...\n");
        return;
    }

    priority = to_int(priority);

    if( priority < 1 || priority > 5 ) {
        tell_object( TP, "The priority must be between 1 and 5.\n] ");
        input_to( (: set_priority :), list, item );
        return;
    }

    item->priority = priority;
    tell_object( TP, "Please enter the number of days the task must be "
        "completed in, or 'q' to quit: ");
    input_to( (: set_deadline :), list, item );

} /* set_priority() */

/** @ignore yes */
void set_creator( string cre, string list, class todo_item item ) {
    cre = lower_case(cre);

    if( cre == "q" ) {
        tell_object( TP, "Aborting...\n");
        return;
    }

    if( !cre || !rank(cre) ) {
        tell_object( TP, "No such player - "+CAP(cre)+".\n] ");
        input_to( (: set_creator :), list, item );
        return;
    }

    if( !creatorp(cre) ) {
        tell_object( TP, CAP(cre)+" is not a creator.\n] ");
        input_to( (: set_creator :), list, item );
        return;
    }

    item->person = cre;
    tell_object( TP, "Please enter the priority level of the task (1-5), "
        "or 'q' to quit: ");
    input_to( (: set_priority :), list, item );

} /* set_creator() */

/** @ignore yes */
private void set_name( string name, string list ) {
    class todo_item item;

    if( name == "q" || name == "Q" ) {
        tell_object( TP, "Aborting...\n");
        return;
    }

    if( !name || name == "" ) {
        tell_object( TP, "You must enter a name for the task.\n] ");
        input_to( (: set_name :), list );
        return;
    }

    foreach( item in tasks[list] ) {
        if( item->taskname == name ) {
            tell_object( TP, "A task called \""+name+"\" already exists on "
                "the "+list+" list, please choose another name.\n] ");
            input_to( (: set_name :), list );
            return;
        }
    }

    item = new( class todo_item, taskname : name );
    tell_object( TP, "Please enter the name of the creator to "
        "assign the task to, or 'q' to quit: ");
    input_to( (: set_creator :), list, item );

} /* set_name() */

/** @ignore yes */
private void set_list( string list ) {
    if( list == "q" || list == "Q" ) {
        tell_object( TP, "Aborting...\n");
        return;
    }

    if( !check_valid_list(list) ) {
        tell_object( TP, "There is no list by the name \""+list+"\".\n] ");
        input_to( (: set_list :) );
        return;
    }

    tell_object( TP, "Please enter the name of the new task, or 'q' to "
        "quit: ");
    input_to( (: set_name :), list );

} /* set_list() */

/** @ignore yes */
private int cmd() {
    if( !lordp(TP) ) {
        tell_object( TP, "Sorry, only lords and above may add tasks.\n");
        return 1;
    }

    tell_object( TP, "Please enter the name of the list to add the task to, "
        "or 'q' to quit: ");
    input_to( (: set_list :) );
    return 1;

} /* cmd() */

/** @ignore yes */
mixed query_patterns() {
    return ({
        "add list <word'name'>",(: create_list( $4[0] ) :),
        "add task", (: cmd :),
        "list <word'list name'>",(: disp_list( $4[0] ) :),
        "remove list <word'name'>",(: remove_list( $4[0] ) :),
        "remove task <word'task'> from <word'list'>",
        (: remove_task( $4[0], $4[1] ) :),
        "complete task <word'task'> on <word'list'>",
        (: complete_task( $4[0], $4[1] ) :),
        "list", (: disp_lists() :),
        "list my tasks", (: disp_tasks( TP->query_name() ) :),
        "list <word'person'>", (: disp_tasks( $4[0] ) :),
        "list tasks <word'person'>", (: disp_tasks( $4[0] ) :),
        "list completed <word'person'>", (: list_completed( $4[0] ) :),
    });
} /* query_patterns() */