dw_fluffos_v2/
dw_fluffos_v2/fluffos-2.9-ds2.05/
dw_fluffos_v2/fluffos-2.9-ds2.05/ChangeLog.old/
dw_fluffos_v2/fluffos-2.9-ds2.05/Win32/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/
dw_fluffos_v2/fluffos-2.9-ds2.05/compat/simuls/
dw_fluffos_v2/fluffos-2.9-ds2.05/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/clone/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/command/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/data/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/etc/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/include/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/inherit/master/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/log/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/compiler/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/efuns/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/single/tests/operators/
dw_fluffos_v2/fluffos-2.9-ds2.05/testsuite/u/
dw_fluffos_v2/fluffos-2.9-ds2.05/tmp/
dw_fluffos_v2/fluffos-2.9-ds2.05/windows/
dw_fluffos_v2/lib/
dw_fluffos_v2/lib/binaries/cmds/
dw_fluffos_v2/lib/binaries/cmds/creator/
dw_fluffos_v2/lib/binaries/cmds/living/
dw_fluffos_v2/lib/binaries/cmds/player/
dw_fluffos_v2/lib/binaries/d/admin/obj/
dw_fluffos_v2/lib/binaries/d/liaison/
dw_fluffos_v2/lib/binaries/global/virtual/
dw_fluffos_v2/lib/binaries/global/virtual/setup_compiler/
dw_fluffos_v2/lib/binaries/obj/handlers/autodoc/
dw_fluffos_v2/lib/binaries/obj/handlers/terrain_things/
dw_fluffos_v2/lib/binaries/obj/misc/
dw_fluffos_v2/lib/binaries/obj/misc/buckets/
dw_fluffos_v2/lib/binaries/obj/monster/
dw_fluffos_v2/lib/binaries/obj/reactions/
dw_fluffos_v2/lib/binaries/obj/reagents/
dw_fluffos_v2/lib/binaries/secure/cmds/creator/
dw_fluffos_v2/lib/binaries/secure/master/
dw_fluffos_v2/lib/binaries/std/
dw_fluffos_v2/lib/binaries/std/dom/
dw_fluffos_v2/lib/binaries/std/effects/object/
dw_fluffos_v2/lib/binaries/std/guilds/
dw_fluffos_v2/lib/binaries/std/languages/
dw_fluffos_v2/lib/binaries/std/races/
dw_fluffos_v2/lib/binaries/std/room/
dw_fluffos_v2/lib/binaries/std/room/basic/
dw_fluffos_v2/lib/binaries/std/shops/
dw_fluffos_v2/lib/binaries/std/shops/inherit/
dw_fluffos_v2/lib/binaries/www/
dw_fluffos_v2/lib/cmds/guild-race/
dw_fluffos_v2/lib/cmds/guild-race/crafts/
dw_fluffos_v2/lib/cmds/guild-race/other/
dw_fluffos_v2/lib/cmds/playtester/
dw_fluffos_v2/lib/cmds/playtester/senior/
dw_fluffos_v2/lib/d/admin/
dw_fluffos_v2/lib/d/admin/log/
dw_fluffos_v2/lib/d/admin/mapper/31-10-01/mapmaker/event/
dw_fluffos_v2/lib/d/admin/meetings/
dw_fluffos_v2/lib/d/admin/obj/
dw_fluffos_v2/lib/d/admin/room/we_care/
dw_fluffos_v2/lib/d/admin/save/
dw_fluffos_v2/lib/d/dist/
dw_fluffos_v2/lib/d/dist/mtf/
dw_fluffos_v2/lib/d/dist/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/chars/
dw_fluffos_v2/lib/d/dist/pumpkin/desert/
dw_fluffos_v2/lib/d/dist/pumpkin/gumboot/
dw_fluffos_v2/lib/d/dist/pumpkin/hospital/
dw_fluffos_v2/lib/d/dist/pumpkin/inherit/
dw_fluffos_v2/lib/d/dist/pumpkin/map/
dw_fluffos_v2/lib/d/dist/pumpkin/plain/
dw_fluffos_v2/lib/d/dist/pumpkin/pumpkin/
dw_fluffos_v2/lib/d/dist/pumpkin/save/
dw_fluffos_v2/lib/d/dist/pumpkin/squash/
dw_fluffos_v2/lib/d/dist/pumpkin/terrain/
dw_fluffos_v2/lib/d/dist/pumpkin/woods/
dw_fluffos_v2/lib/d/dist/start/
dw_fluffos_v2/lib/d/learning/TinyTown/buildings/
dw_fluffos_v2/lib/d/learning/TinyTown/map/
dw_fluffos_v2/lib/d/learning/TinyTown/roads/
dw_fluffos_v2/lib/d/learning/add_command/
dw_fluffos_v2/lib/d/learning/arms_and_weps/
dw_fluffos_v2/lib/d/learning/chars/
dw_fluffos_v2/lib/d/learning/cutnpaste/
dw_fluffos_v2/lib/d/learning/examples/npcs/
dw_fluffos_v2/lib/d/learning/examples/player_houses/npcs/
dw_fluffos_v2/lib/d/learning/examples/terrain_map/basic/
dw_fluffos_v2/lib/d/learning/functions/
dw_fluffos_v2/lib/d/learning/handlers/
dw_fluffos_v2/lib/d/learning/help_topics/npcs/
dw_fluffos_v2/lib/d/learning/help_topics/objects/
dw_fluffos_v2/lib/d/learning/help_topics/rcs_demo/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/crowd/
dw_fluffos_v2/lib/d/learning/help_topics/rooms/situations/
dw_fluffos_v2/lib/d/learning/items/
dw_fluffos_v2/lib/d/learning/save/
dw_fluffos_v2/lib/d/liaison/
dw_fluffos_v2/lib/d/liaison/NEWBIE/doc/
dw_fluffos_v2/lib/d/liaison/NEWBIE/save/oldlog/
dw_fluffos_v2/lib/db/
dw_fluffos_v2/lib/doc/
dw_fluffos_v2/lib/doc/creator/
dw_fluffos_v2/lib/doc/creator/autodoc/include/reaction/
dw_fluffos_v2/lib/doc/creator/autodoc/include/ritual_system/
dw_fluffos_v2/lib/doc/creator/autodoc/include/talker/
dw_fluffos_v2/lib/doc/creator/autodoc/include/terrain_map/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/baggage/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clock/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/clothing/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/cont_save/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/corpse/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/money/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/monster/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/scabbard/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/service_provider/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/state_changer/
dw_fluffos_v2/lib/doc/creator/autodoc/obj/wand/
dw_fluffos_v2/lib/doc/creator/autodoc/std/book_dir/
dw_fluffos_v2/lib/doc/creator/autodoc/std/key/
dw_fluffos_v2/lib/doc/creator/autodoc/std/learning/
dw_fluffos_v2/lib/doc/creator/autodoc/std/map/
dw_fluffos_v2/lib/doc/creator/autodoc/std/race/
dw_fluffos_v2/lib/doc/creator/autodoc/std/weapon_logic/
dw_fluffos_v2/lib/doc/creator/files/
dw_fluffos_v2/lib/doc/creator/policy/
dw_fluffos_v2/lib/doc/creator/room/
dw_fluffos_v2/lib/doc/effects/
dw_fluffos_v2/lib/doc/ideas/
dw_fluffos_v2/lib/doc/known_command/
dw_fluffos_v2/lib/doc/lpc/basic_manual/
dw_fluffos_v2/lib/doc/lpc/intermediate/
dw_fluffos_v2/lib/doc/new/add_command/
dw_fluffos_v2/lib/doc/new/handlers/
dw_fluffos_v2/lib/doc/new/living/
dw_fluffos_v2/lib/doc/new/living/race/
dw_fluffos_v2/lib/doc/new/living/spells/
dw_fluffos_v2/lib/doc/new/player/
dw_fluffos_v2/lib/doc/new/room/guild/
dw_fluffos_v2/lib/doc/new/room/outside/
dw_fluffos_v2/lib/doc/new/room/storeroom/
dw_fluffos_v2/lib/doc/object/
dw_fluffos_v2/lib/doc/playtesters/
dw_fluffos_v2/lib/doc/policy/
dw_fluffos_v2/lib/doc/weapons/
dw_fluffos_v2/lib/global/handlers/
dw_fluffos_v2/lib/global/virtual/setup_compiler/
dw_fluffos_v2/lib/include/
dw_fluffos_v2/lib/include/cmds/
dw_fluffos_v2/lib/include/effects/
dw_fluffos_v2/lib/include/npc/
dw_fluffos_v2/lib/include/shops/
dw_fluffos_v2/lib/net/daemon/chars/
dw_fluffos_v2/lib/net/inherit/
dw_fluffos_v2/lib/net/intermud3/
dw_fluffos_v2/lib/net/intermud3/services/
dw_fluffos_v2/lib/net/obj/
dw_fluffos_v2/lib/net/save/
dw_fluffos_v2/lib/net/smnmp/
dw_fluffos_v2/lib/net/snmp/
dw_fluffos_v2/lib/obj/amulets/
dw_fluffos_v2/lib/obj/b_day/
dw_fluffos_v2/lib/obj/examples/
dw_fluffos_v2/lib/obj/food/alcohol/
dw_fluffos_v2/lib/obj/food/chocolates/
dw_fluffos_v2/lib/obj/food/fruits/
dw_fluffos_v2/lib/obj/food/meat/
dw_fluffos_v2/lib/obj/food/nuts/
dw_fluffos_v2/lib/obj/food/seafood/
dw_fluffos_v2/lib/obj/food/vegetables/
dw_fluffos_v2/lib/obj/fungi/
dw_fluffos_v2/lib/obj/furnitures/artwork/
dw_fluffos_v2/lib/obj/furnitures/bathroom/
dw_fluffos_v2/lib/obj/furnitures/beds/
dw_fluffos_v2/lib/obj/furnitures/cabinets/
dw_fluffos_v2/lib/obj/furnitures/chairs/
dw_fluffos_v2/lib/obj/furnitures/chests/
dw_fluffos_v2/lib/obj/furnitures/clocks/
dw_fluffos_v2/lib/obj/furnitures/crockery/
dw_fluffos_v2/lib/obj/furnitures/cupboards/
dw_fluffos_v2/lib/obj/furnitures/cushions/
dw_fluffos_v2/lib/obj/furnitures/fake_plants/
dw_fluffos_v2/lib/obj/furnitures/lamps/
dw_fluffos_v2/lib/obj/furnitures/mirrors/
dw_fluffos_v2/lib/obj/furnitures/outdoor/
dw_fluffos_v2/lib/obj/furnitures/safes/
dw_fluffos_v2/lib/obj/furnitures/shelves/
dw_fluffos_v2/lib/obj/furnitures/sideboards/
dw_fluffos_v2/lib/obj/furnitures/sofas/
dw_fluffos_v2/lib/obj/furnitures/stoves/
dw_fluffos_v2/lib/obj/furnitures/tables/
dw_fluffos_v2/lib/obj/furnitures/wardrobes/
dw_fluffos_v2/lib/obj/handlers/
dw_fluffos_v2/lib/obj/handlers/autodoc/
dw_fluffos_v2/lib/obj/jewellery/anklets/
dw_fluffos_v2/lib/obj/jewellery/bracelets/
dw_fluffos_v2/lib/obj/jewellery/earrings/
dw_fluffos_v2/lib/obj/jewellery/misc/
dw_fluffos_v2/lib/obj/jewellery/necklaces/
dw_fluffos_v2/lib/obj/jewellery/rings/
dw_fluffos_v2/lib/obj/media/
dw_fluffos_v2/lib/obj/misc/buckets/
dw_fluffos_v2/lib/obj/misc/jars/
dw_fluffos_v2/lib/obj/misc/papers/
dw_fluffos_v2/lib/obj/misc/player_shop/
dw_fluffos_v2/lib/obj/misc/shops/
dw_fluffos_v2/lib/obj/misc/traps/
dw_fluffos_v2/lib/obj/monster/
dw_fluffos_v2/lib/obj/monster/godmother/
dw_fluffos_v2/lib/obj/monster/transport/
dw_fluffos_v2/lib/obj/plants/inherit/
dw_fluffos_v2/lib/obj/potions/
dw_fluffos_v2/lib/open/boards/
dw_fluffos_v2/lib/save/autodoc/
dw_fluffos_v2/lib/save/bank_accounts/
dw_fluffos_v2/lib/save/boards/frog/
dw_fluffos_v2/lib/save/books/bed_catalog/
dw_fluffos_v2/lib/save/creators/
dw_fluffos_v2/lib/save/mail/
dw_fluffos_v2/lib/save/mail/p/
dw_fluffos_v2/lib/save/soul/data/
dw_fluffos_v2/lib/save/tasks/
dw_fluffos_v2/lib/save/vaults/
dw_fluffos_v2/lib/secure/cmds/lord/
dw_fluffos_v2/lib/secure/config/
dw_fluffos_v2/lib/secure/items/
dw_fluffos_v2/lib/secure/player/
dw_fluffos_v2/lib/soul/
dw_fluffos_v2/lib/soul/i/
dw_fluffos_v2/lib/soul/j/
dw_fluffos_v2/lib/soul/k/
dw_fluffos_v2/lib/soul/o/
dw_fluffos_v2/lib/soul/q/
dw_fluffos_v2/lib/soul/to_approve/
dw_fluffos_v2/lib/soul/u/
dw_fluffos_v2/lib/soul/v/
dw_fluffos_v2/lib/soul/wish_list/
dw_fluffos_v2/lib/soul/y/
dw_fluffos_v2/lib/soul/z/
dw_fluffos_v2/lib/std/creator/
dw_fluffos_v2/lib/std/effects/
dw_fluffos_v2/lib/std/effects/attached/
dw_fluffos_v2/lib/std/effects/external/
dw_fluffos_v2/lib/std/effects/fighting/
dw_fluffos_v2/lib/std/effects/other/
dw_fluffos_v2/lib/std/environ/
dw_fluffos_v2/lib/std/guilds/
dw_fluffos_v2/lib/std/hospital/
dw_fluffos_v2/lib/std/house/
dw_fluffos_v2/lib/std/house/onebedhouse/
dw_fluffos_v2/lib/std/house/onebedhut/
dw_fluffos_v2/lib/std/house/tworoomflat/
dw_fluffos_v2/lib/std/languages/
dw_fluffos_v2/lib/std/liquids/
dw_fluffos_v2/lib/std/nationality/
dw_fluffos_v2/lib/std/nationality/accents/
dw_fluffos_v2/lib/std/nationality/accents/national/
dw_fluffos_v2/lib/std/nationality/accents/regional/
dw_fluffos_v2/lib/std/npc/goals/
dw_fluffos_v2/lib/std/npc/goals/basic/
dw_fluffos_v2/lib/std/npc/goals/misc/
dw_fluffos_v2/lib/std/npc/inherit/
dw_fluffos_v2/lib/std/npc/plans/
dw_fluffos_v2/lib/std/npc/plans/basic/
dw_fluffos_v2/lib/std/outsides/
dw_fluffos_v2/lib/std/races/shadows/
dw_fluffos_v2/lib/std/room/basic/topography/
dw_fluffos_v2/lib/std/room/controller/
dw_fluffos_v2/lib/std/room/controller/topography/
dw_fluffos_v2/lib/std/room/furniture/games/
dw_fluffos_v2/lib/std/room/furniture/inherit/
dw_fluffos_v2/lib/std/room/inherit/carriage/
dw_fluffos_v2/lib/std/room/inherit/topography/
dw_fluffos_v2/lib/std/room/punishments/
dw_fluffos_v2/lib/std/room/topography/area/
dw_fluffos_v2/lib/std/room/topography/iroom/
dw_fluffos_v2/lib/std/room/topography/milestone/
dw_fluffos_v2/lib/std/shadows/
dw_fluffos_v2/lib/std/shadows/attached/
dw_fluffos_v2/lib/std/shadows/curses/
dw_fluffos_v2/lib/std/shadows/disease/
dw_fluffos_v2/lib/std/shadows/fighting/
dw_fluffos_v2/lib/std/shadows/room/
dw_fluffos_v2/lib/std/shops/controllers/
dw_fluffos_v2/lib/std/shops/objs/
dw_fluffos_v2/lib/std/shops/player_shop/
dw_fluffos_v2/lib/std/shops/player_shop/office_code/
dw_fluffos_v2/lib/std/socket/
dw_fluffos_v2/lib/www/
dw_fluffos_v2/lib/www/external/autodoc/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/
dw_fluffos_v2/lib/www/external/java/telnet/Documentation/images/
dw_fluffos_v2/lib/www/external/java/telnet/examples/
dw_fluffos_v2/lib/www/external/java/telnet/tools/
dw_fluffos_v2/lib/www/pics/
dw_fluffos_v2/lib/www/secure/creator/
dw_fluffos_v2/lib/www/secure/editors/
dw_fluffos_v2/lib/www/secure/survey_results/
dw_fluffos_v2/win32/
/**
 * The standard inheritable object for player-run shop offices.
 * 
 * <p><b>Description</b></p>
 * <p>This office is the nerve centre of the shop. Most of the data
 * structures are defined and maintained from here, and virtually all
 * of the managerial functions are forwarded here. It is this object
 * that passes the common variables across to other files as they call
 * for them. This minimises the complexity of setting up each object - as
 * long as they point to this object, and this object is correctly set up,
 * the objects will know which shop they belong to, who the employees are,
 * who the proprietor is etc. 
 * </p>
 * <p>Before the shop will function correctly, it must be registered with
 * the handler - see set_very_short()
 * </p>
 * <p>Most of the functions defined in the office are not needed by
 * creators. Those that are needed are shown in the examples. Other
 * functions are not necessary, but may be useful. 
 * </p>
 * <p>The source to this object is split into 15 different files. The
 * main file, office.c includes the other files under the office_code
 * directory. This is intended to ease code maintenance as the total
 * size of the office code (as of December 2000) is around 165k. 
 * </p>
 * <p>In general, the functions contained in office.c are those intended
 * to be used directly by creators. The other functions are called
 * internally by the shop. 
 * </p>
 * <p>The data itself is also saved into several files. The data is
 * arranged into these files to minimise the amount of disk activity
 * when changes are made. For example, employee data changes every time an
 * employee does something. The list of applicants, however, changes only
 * when an application status changes. They are, therefore, saved into
 * seperate files. Also, each save call is subject to a callout, and will
 * limit the amount of disk writing actually done. The only data not stored
 * by this file is the stock data, which is saved by each cabinet
 * individually. All data and logs are saved into several files within
 * a directory "/d/(domain)/save/player_shops/(shop_very_short)/".
 * In addition, some data are cleared if it hasn't been used for a while.
 * This will typically save up to 100k of memory for a store the size of
 * Tarnach's.
 * </p>
 * <p>The shop supports notice boards, posting all hirings, promotions,
 * bonus amounts in addition to any posts requested in the inheriting
 * object. In the absence of a board, all posts are mailed to each employee
 * and each employee will have access to an additional "memo" command in
 * the office. 
 * </p>
 * <p>Applications are handled automatically, with managers voting whether
 * to accept or reject an application. On gaining positive votes from at
 * least 50% of the managers, an applicant is hired. If they receive more
 * than 50% negative votes, they are rejected. If there are insufficient
 * votes to settle the decision, an applicant will be hired if more managers
 * have voted for than against. Policy suggestions are handled in a similar
 * way. 
 * </p>
 * <p>The shop's two main administration routines are run on a regular
 * basis. The first of these is run every day and is responsible for
 * checking that employees are still valid players (not deleted chars or
 * creators). It conducts automatic promotions, and handles demotions for
 * inactive employees. It also updates the lists of declined applicants
 * and banned people and removes that status if applicable. Finally, it
 * calls the check_hire_list() function to see if we can hire any new
 * employees. 
 * </p>
 * <p>The second is run every Discworld month. This review involves paying
 * employees directly into their nominated bank account, and awarding
 * bonuses based on the current value of the bonus fund. 
 * </p>
 * 
 * @example
 * #include "path.h"
 * 
 * inherit "/std/shops/player_shop/office";
 *  
 * void setup()
 * {
 *    set_light(60);
 *    set_place("Lancre");
 *    set_proprietor("Tarnach Fendertwin");
 *    set_shop_name("Tarnach Fendertwin's Quality Consumables (Creel Springs)");
 *    set_very_short("TFQC-CS");
 *    set_channel("tarnachcs", 0);
 *    set_shopkeeper(PATH + "shopkeeper");
 *    set_stock_policy("magical spell components");
 * 
 *    set_shop_front(PATH+ "front");
 *    set_counter(PATH+ "counter");
 *    set_storeroom(PATH+ "storeroom");
 *    set_directions("east", "east", "east");
 * 
 *    set_short("office of Tarnach's shop");
 *    set_long("This room is the office of the Creel Springs branch of "
 *      "Tarnach Fendertwin's Quality Consumables.  There is a door to the "
 *      "managers' office in the south wall.\n");
 *    add_sign("The sign is a small piece of paper stuck to the wall.\n",
 *      "This seems to be a handwritten note from Tarnach himself.  "
 *      "The handwriting, not to mention the spelling and the grammar, "
 *      "is appalling, so it's difficult to make out much.  All you "
 *      "can understand is something about what the \"office\" is for.",
 *      "sign", "sign" )->add_property( "there", "on one wall");
 *    add_exit("east", PATH+ "counter", "door");
 *    add_manager_exit("south", PATH + "mgr_office");
 * }
 * 
 * @see /include/player_shop.h
 * @see /std/shops/player_shop/mgr_office.c
 * @see /std/shops/player_shop/counter.c
 * @see /std/shops/player_shop/storeroom.c
 * @see /std/shops/player_shop/shop_front.c
 * @see /std/shops/player_shop/shopkeeper.c
 * @author Ringo
 * @started 1st August 1999
 */
inherit "/std/room/basic_room";

#include <player_shop.h>
#include <mail.h>
#include <board.h>
#include <money.h>
#include <move_failures.h>
#include <refresh.h>
#include "office.h"


/*
 * Globals
 */
private nosave string _proprietor = UNSET_STR,
                      _shop_name = UNSET_STR,
                      _very_short = UNSET_STR, 
                      _place = UNSET_STR, 
                      _channel = UNSET_STR,
                      _storeroom = "",
                      _shop_front = "",
                      _counter = "",
                      _mgr_office = "",
                      _store_dir = "",
                      _counter_dir = "",
                      _shop_dir = "",
                      _shopkeeper = "",
                      _stock_policy = "",
                      _cab_name = "",
                      _review_month = "",
                      _savedir = "",
                      _creator = CREATOR;

private nosave object _chart = 0,
                      _board = 0,
                      _notice = 0;

private nosave mapping _history = 0,
                       _applicants = 0,
                       _policies = 0,
                       _new_policies = 0,
                       _list = ([]),
                       _times = ([]),
                       _employees = ([]);

/** Used to keep track of (and remove) call_outs */
private nosave int _call_save = 0,
                   _call_hist = 0,
                   _call_hist_clear = 0,
                   _call_times = 0,
                   _call_hire_list = 0,
                   _call_mail_hirees = 0,
                   _call_summon = 0,
                   _call_emps = 0,
                   _call_review = 0,
                   _call_apps = 0,
                   _call_apps_clear = 0,
                   _call_pols = 0,
                   _call_pols_clear = 0,
                   _call_newpols = 0,
                   _call_newpols_clear = 0;

private string *_retired = ({}),
               *_got_bonus = ({}),
               _last_month = "last month",
               _eom = CREATOR;

private mapping _baddies = ([]),
                _declined = ([]),
                _accounts = (["profit":0,"bonus":0]);

private int _max_emp = MAX_EMP,
            _bonus_val = 0, 
            _bonus = 0, 
            _pay_val = 4,
            _num_cabinets = MIN_CABINETS,
            _net_takings = 0;

private mixed *_register = ({});

/**
 * @ignore yes
 */
void create()
{  
   do_setup++;
   ::create();
   do_setup--;
   if (!do_setup)
   {
      this_object()->setup();
      this_object()->reset();
   }
   seteuid("Room");
   add_property("determinate", "");
   add_help_file("player_shop_office");
} /* create() */

/**
 * @ignore yes
 * Include rest of source - this is split up to keep filesizes within a
 * practical size limit.  This should make maintaining the source less of a
 * nightmare.  Only public functions will be found in this file.
 */
#include "office_code/admin.c"         // misc admin functions
#include "office_code/applications.c"  // application-related functions
#include "office_code/baddies.c"       // banning-related functions
#include "office_code/cabinets.c"      // cabinet-related functions
#include "office_code/emp_cmd.c"       // employee commands
#include "office_code/lists.c"         // listing functions
#include "office_code/logging.c"       // log-related functions
#include "office_code/masked.c"        // masked functions
#include "office_code/memo.c"          // memo functions
#include "office_code/personnel.c"     // personnel-related functions
#include "office_code/policies.c"      // policy-related functions
#include "office_code/review.c"        // daily & monthly review functions
#include "office_code/save.c"          // saving-related functions
#include "office_code/stock.c"         // stock-related functions

/******************************************************************************
 ******************************************************************************
 *                       START OF PUBLIC FUNCTIONS                            *
 ******************************************************************************
 ******************************************************************************/

/**
 * Set the exit to the managers' office.
 * This method also modifies the exit to allow only managers to enter the
 * managers' office.
 * @example add_manager_exit( "east", PATH + "tarnach's_man_office" );
 * @param dir the direction of the exit.
 * @param path the full path and filename to the managers' office of the shop.
 */
protected void add_manager_exit(string dir, string path)
{
   add_exit(dir, path, "door");
   modify_exit(dir, ({"function", ({this_object(),
     "check_manager"}), "door short", "office door", "door long",
     "There is a sign on the door which reads: \""+ _proprietor+ 
     "- Private\".\n"}));
   _mgr_office = path;
}
/* set_mgr_office() */


/**
 * Query the list of applicants.
 * This method returns the list of applicants as a mapping formatted
 * as follows:<br>
 * ([ "name": type, time, ({ for }), ({ against }), ({ abstain }), ])
 * @return the applicants mapping formatted as above.
 */
mapping get_applicants()
{
   load_applicants();
   clear_applicants();
   return copy(_applicants + ([]));
}

/**
 * Query the people banned from the shop.
 * This method returns a mapping of the people banned from this shop, along
 * with the time that they were banned, the person banning them, and the 
 * reason they were banned.  The format for this mapping is:<br>
 * ([ person:({ reason, banner, time }) ])
 * @return the mapping, formatted as above.
 */
mapping get_baddies() { return copy(_baddies + ([])); }

/**
 * Query the list of employees.
 * This method returns the list of employees, sorted alphabetically.
 * @see get_supervisors()
 * @see get_managers()
 * @see get_retired()
 * @return the sorted array of employees.
 */
string *get_employees()
{
   string *employees = m_indices(_employees);

   /* Don't include people with the supervisor bit set */
   foreach (string word in employees)
      if (_employees[word][EMP_POINTS] & SUPERVISOR)
         employees -= ({word});
   return copy(sort_array(employees, 1));
}
/* get_employees() */

/**
 * Query the list of managers.
 * This method returns the list of managers, sorted alphabetically.
 * @see get_employees()
 * @see get_supervisors()
 * @see get_retired()
 * @return the sorted array of managers.
 */
string *get_managers()
{
   return copy(sort_array(keys(filter(_employees,
        (: _employees[$1][EMP_POINTS] & MANAGER :))), 1));
}
/* get_managers() */

/**
 * Query the policy suggestions.
 * These are the policies that have been proposed but not yet implemented.
 * @see get_policies()
 * @see query_policy()
 * @return a mapping of the suggested shop policies.
 */
mapping get_new_policies()
{ 
   load_new_policies();
   clear_new_policies();
   return copy(_new_policies);
}

/**
 * Query the policies.
 * These are the policies currently in effect.
 * @see get_new_policies()
 * @see query_policy()
 * @return a mapping of the shop policies.
 */
mapping get_policies(int type)
{
   load_policies();
   clear_policies();
   if (type)
      return copy(filter(_policies, (: _policies[$1][1] :)));
   else
      return copy(filter(_policies, (: !_policies[$1][1] :)));
}
/* get_policies() */

/**
 * Query the list of retired managers.
 * This method returns the list of retired managers, sorted alphabetically.
 * @see get_employees()
 * @see get_supervisors()
 * @see get_managers()
 * @return the sorted array of retired managers.
 */
string *get_retired() { return copy(sort_array(_retired, 1)); }

/**
 * Query the list of supervisors.
 * This method returns the list of supervisors, sorted alphabetically.
 * @see get_employees()
 * @see get_managers()
 * @see get_retired()
 * @return the sorted array of supervisors.
 */
string *get_supervisors()
{
   string *supervisors = keys(filter(_employees,
        (: _employees[$1][EMP_POINTS] & SUPERVISOR :)));

   /* Managers also have the supervisor bit set, so don't
    * include them in this list.
    */
   foreach (string word in supervisors)
      if (_employees[word][EMP_POINTS] & MANAGER)
         supervisors -= ({word});
   return copy(sort_array(supervisors, 1));
}
/* get_supervisors() */

/**
 * Query the number of employees currently clocked in.
 * This function will also clock out any employees that are no longer on DW.
 * @return the number of employees clocked in. 
 */
int num_employees_in()
{
   int any = 0;

   foreach (string word in m_indices(_employees))
      if (_employees[word][EMP_POINTS] & CLOCKED_IN)
      {
         if (_employees[word][EMP_POINTS] & NPC) continue;
         if (!find_player(word) || !interactive(find_player(word)))
         {
            reset_employee(word, CLOCKED_IN);
            shop_log(GENERAL, word, "was clocked out", UNPAID);
         }
         else any++;
      }
   return any;
}
/* num_employees_in() */

/**
 * Determine if this person has applied for a job.
 * @param player the player to query.
 * @return APPLIED if applied, HIRED if voted in, AWAITING if awaiting 
 * a vacancy.  Otherwise, will return FALSE.
 */
int query_applicant(string player)
{
   load_applicants();
   clear_applicants();
   if (!sizeof(_applicants)) return FALSE;
   if (_applicants[player]) return copy(_applicants[player][APP_TYPE]);
   return FALSE;
}
/* query_applicant() */

/**
 * Determine if this person is banned from the shop.
 * @param player the player to query.
 * @return the time of the ban if banned, FALSE if not banned.
 */
int query_baddie(string player)
{
   if (!m_sizeof(_baddies)) return FALSE;
   if (_baddies[player]) return copy(_baddies[player][BAD_TIME]);
   return FALSE;
}
/* query_baddie() */

/**
 * Query the value of the bonus account.
 * This is the current value of the bonus account.  Will need converting to 
 * local currency if it is to be displayed.
 * @see query_profit()
 * @return the value of the bonus account.
 */
int query_bonus() { return copy(_accounts["bonus"]); }

/**
 * Query the channel used by the shop.
 * @see set_channel()
 * @return the channel in use by this shop
 */
string query_channel() { return copy(_channel); }

/**
 * Query the path to the shop counter.
 * @see set_counter()
 * @return the path to the counter.
 */
string query_counter() { return copy(_counter); }

/**
 * Query the maintainer of this shop's files.
 * @see set_creator()
 * @return the person responsible for this shop.
 */
void query_creator(string creator) { return copy(_creator); }

/**
 * Determine if a player was declined for a job.
 * This method is used to determine if there is a declined application
 * registered for a player.
 * @param player the player to query.
 * @return FALSE, or the time at which the applicant was declined. 
 */
int query_declined(string player)
{
   if (!sizeof(_declined)) return FALSE;
   if (_declined[player]) return copy(_declined[player]);
   return FALSE;
}
/* query_declined() */


/**
 * Determine if this person is an employee of the shop.
 * @see query_supervisor()
 * @see query_manager()
 * @see query_retired()
 * @param player the player to query.
 * @return the employee's points, or FALSE if not an employee.
 */
int query_employee(string player)
{
   if (_employees[player]) return copy(_employees[player][EMP_POINTS]);
   return FALSE;
}
/* query_employee() */

/**
 * Return the employee data.
 * This includes only active employees - retired managers are not included.
 * The data is formatted as:<br>
 * ([ employee:({ points, time, bank, pay, inactive, nobonus, nopromote }) ])<br>
 * @return the employee mapping, formatted as above.
 */
mapping query_employees() { return copy(_employees + ([])); }

/**
 * Query the list of items sold by the shop.
 * Generates an array of the keys to the list mapping.
 * @see query_list_mapping()
 * @see query_list_string()
 * @return the list of items in array form.
 */
string *query_list_array() { return copy(m_indices(_list) + ({})); }

/**
 * Query the list of items sold by the shop.
 * @see query_list_array()
 * @see query_list_string()
 * @return the list of items in mapping form.
 */
mapping query_list_mapping() { return copy(_list) + ([]); }

/**
 * Query the list of items sold by the shop.
 * Generates a list of all items bought & sold by this shop, and outputs a
 * multiple short string for use in displays.
 * @see query_list_array()
 * @see query_list_mapping()
 * @return the list of items.
 */
string query_list_string()
{
   if (!m_sizeof(_list)) return "absolutely nothing at the moment";
   return query_multiple_short(m_indices(_list));
}
/* query_list_string() */

/**
 * Determine if this person is a manager of this shop.
 * @see query_employee()
 * @see query_supervisor()
 * @see query_retired()
 * @param player the player to query.
 * @return TRUE or FALSE
 */
int query_manager(string player)
{
   if (_employees[player]) return (_employees[player][EMP_POINTS] & MANAGER);
   return FALSE;
}
/* query_manager() */

/**
 * Query the maximum number of employees.
 * @return the maximum number of employees allowed at this shop.
 */
int query_maxemp() { return copy(_max_emp); }

/**
 * Query the path to the managers' office.
 * @return the path to the managers' office.
 */
string query_mgr_office() { return copy(_mgr_office); }

/**
 * Query the number of storeroom cabinets.
 * @return the number of cabinets in the storeroom.
 */
int query_num_cabinets() { return copy(_num_cabinets); }

/**
 * Query the base pay rate.
 * This is the base pay rate set by the managers; the amount each employee
 * will receive for a single transaction.
 * @return the value of the base pay rate
 */
int query_pay() { return copy(_pay_val); }

/**
 * Query the location of this shop.
 * @see set_place()
 * @return the location of the shop
 */
string query_place() { return copy(_place); }

/**
 * Determine if a shop policy exists.
 * @see get_policies()
 * @see get_new_policies()
 * @param policy The name of the policy to query.
 * @return 2 if it is already policy, 1 if it is a proposal, else 0
 */
int query_policy(string policy)
{
   load_policies();
   clear_policies();
   if (m_sizeof(_policies) && _policies[policy]) return 2;
   load_new_policies();
   clear_new_policies();
   if (m_sizeof(_new_policies) && _new_policies[policy]) return 1;
   return 0;
}
/* query_policy() */

/**
 * Query the value of the profit account.
 * This is the current value of the profit account.  Will need converting to 
 * local currency if it is to be displayed.
 * @see query_bonus()
 * @return the value of the profit account
 */
int query_profit() { return copy(_accounts["profit"]); }

/**
 * Query the name of the proprietor.
 * @see set_proprietor()
 * @return the name of the proprietor
 */
string query_proprietor() { return copy(_proprietor); }

/**
 * Determine if this person is a retired manager of this shop.
 * @see query_employee()
 * @see query_supervisor()
 * @see query_manager()
 * @param player The player to query.
 * @return TRUE or FALSE
 */
int query_retired(string player)
{
   return (member_array(player, _retired) == -1)?FALSE:TRUE;
}
/* query_retired() */

/** @ignore yes */
string query_savedir() { return copy(_savedir); }

/**
 * Query the path to the shop front.
 * @see set_shop_front()
 * @return the path to the shop front
 */
string query_shop_front() { return copy(_shop_front); }

/**
 * Query the full name of the shop.
 * @see set_shop_name()
 * @return the full name of the shop
 */
string query_shop_name() { return copy(_shop_name); }

/**
 * Query the shopkeeper name.
 * @see set_shopkeeper()
 * @return the name of the shopkeeper
 */
string query_shopkeeper() { return copy(_shopkeeper); }


/**
 * Query number of items in stock.
 * Determines the number of a specific item currently held by this shop.
 * @param items the item to query
 * @return the number of 'items' in stock
 */
int query_stock(string items) { return _storeroom->query_num_items(items, 0); }

/**
 * Query the path to the storeroom.
 * @see set_storeroom()
 * @return the path to the storeroom
 */
string query_storeroom() { return copy(_storeroom); }

/**
 * Determine if this person is a supervisor of this shop.
 * @see query_employee()
 * @see query_manager()
 * @see query_retired()
 * @param player The player to query.
 * @return TRUE or FALSE
 */
int query_supervisor(string player)
{ 
   if (_employees[player])
      return (_employees[player][EMP_POINTS] & SUPERVISOR);
   return FALSE;
}
/* query_supervisor() */

/**
 * Save the employee data file.
 * This method uses a call_out to help minimise the amount of disk activity
 * during normal operations of the shop.  The very short name of the shop
 * must have been set previously.
 * @see save_me()
 * @see set_very_short()
 */
protected void save_emps()
{
   if (_very_short == UNSET_STR) return;
   remove_call_out(_call_emps);
   _call_emps = call_out((: do_save_emps() :), SAVE_DELAY);
}
/* save_emps() */

/**
 * Save the shop data file.
 * This method uses a call_out to help minimise the amount of disk activity
 * during normal operations of the shop.  The very short name of the shop
 * must have been set previously.
 * @see save_emps()
 * @see set_very_short()
 */
protected void save_me()
{
   if (_very_short == UNSET_STR) return;
   remove_call_out(_call_save);
   _call_save = call_out((: do_save() :), SAVE_DELAY);
}
/* save_me() */

/**
 * Set the channel used by the shop.
 * This sets the channel used by the employees' badges, and also the
 * name of the board.  If a board has been set-up for this shop, this
 * function will also add the board into the room.
 * @example set_channel( "tarnachcs", 0 );
 * @see query_channel()
 * @param name the name of the channel.
 * @param board non-zero if a board exists for this shop.
 */
protected void set_channel(string name, int board)
{
   _channel = lower_case(name);
   if (board)
   {
      _board = clone_object("/obj/misc/board");
      _board->set_datafile(name);
      _board->move(this_object());
   }
}
/* set_channel() */

/**
 * Set the path to the counter.
 * This is the full path and filename of the counter object to be used by this
 * shop.
 * @example set_counter( PATH + "counter" );
 * @see query_counter()
 * @param path The full path and filename to the shop's counter.
 */
protected void set_counter(string path) { _counter = path; }

/**
 * Set the creator of this shop.
 * This person will receive all applications, complaints, suggestions
 * etc in the absence of any managers.  Default is set by CREATOR in
 * <player_shop.h>
 * @example set_creator( "ringo" );
 * @see query_creator()
 * @param creator The person responsible for this shop.
 */
protected void set_creator(string creator) { _creator = creator; }

/**
 * Set the directions to other parts of the shop.
 * This function is used by the npc shopkeeper to navigate around the shop, 
 * using the exits at the given directions.  These directions should be the 
 * standard "north", "south", "up" etc.
 * @example set_directions( "southeast", "southeast", "southeast" );
 * @param store the direction to the storeroom.
 * @param counter the direction to the counter.
 * @param shop the direction to the shop front.
 */
protected void set_directions(string store, string counter, string shop)
{
   _store_dir = store;
   _counter_dir = counter;
   _shop_dir = shop;
}
/* set_directions() */

/**
 * Set the location of the shop.
 * This is used by the money handling functions to determine which 
 * currency to use and therefore should be one of the locations returned
 * by the query_all_places() function in /obj/handlers/money_handler
 * @example set_place( "Lancre" );
 * @see query_location()
 * @param place the location of this shop.
 */
protected void set_place(string place) { _place = place; }

/**
 * Set the name of the proprietor.
 * A fictional name; the owner of this establishment.  All administration
 * board posts & mudmails will be sent by this name.
 * @example set_proprietor( "Tarnach Fendertwin" );
 * @see query_proprietor()
 * @param name the name of the proprietor.
 */
protected void set_proprietor(string name) { _proprietor = name; }

/**
 * Set the path to the customer area.
 * @example set_shop_front( PATH + "shopfront" );
 * @see query_shop_front()
 * @param path the full path and filename to the customer area of the shop.
 */
protected void set_shop_front(string path) { _shop_front = path; }

/**
 * Set the full name of the shop.
 * This is used throughout the shop, and passed to the shop front as the
 * short description for the shop.
 * @example set_shop_name( "Tarnach Fendertwin's Quality Consumables (Creel Springs)" );
 * @see query_shop_name()
 * @param name the name of the shop.
 */
protected void set_shop_name(string name) { _shop_name = name; }

/**
 * Set the npc shopkeeper object.
 * @example set_shopkeeper( PATH + "shopkeeper" );
 * @see /std/shops/player_shop/shopkeeper.c
 * @param path the full path to the shopkeeper.
 */
protected void set_shopkeeper(string path)
{ 
   _shopkeeper = path;
   path=_shopkeeper->query_name();
   if (!_employees || !_employees[path])
   {
      _employees += ([path:EMP_MAP]);
      _employees[path][EMP_POINTS] = EMPLOYEE + NPC; 
   }
}

/**
 * Set the path to the storeroom.
 * @example set_storeroom( PATH + "storeroom" );
 * @see query_storeroom()
 * @param path the full path and filename to the storeroom of the shop.
 */
protected void set_storeroom(string path) { _storeroom = path; }

/**
 * Set the stock's main policy.
 * This is a general description of the items that this store deals in.
 * @example set_stock_policy( "magical spell components" );
 * @param desc the main stock description.
 */
protected void set_stock_policy(string desc) { _stock_policy = desc; }

/**
 * Set the very short name of the shop.
 * This is used in many places including save-file names, setting up 
 * player-titles, and mail headers.  It should be no more than around
 * 4 or 5 chars in length.  This function also restores all saved data.
 * You must register this name by calling add_shop() in the handler.
 * @example set_very_short( "TFQC-CS" );
 * @see shop_very_short()
 * @see /obj/handlers/player_shop
 * @param name the very short name.
 */
protected void set_very_short(string name)
{
   if (PLAYER_SHOP->query_shop(name) != file_name(this_object()))
      return;
   _very_short = name;
   _savedir = sprintf("/save/player_housing/%s/player_shops/%s/",
      lower_case(geteuid(this_object())), name);
   if (file_size(_savedir+ "shop_data.o") > 0)
      unguarded((: restore_object, _savedir+ "shop_data" :));
   if (file_size(_savedir+ "employees") > 0)
      _employees = restore_variable(unguarded((: read_file,
        _savedir+ "employees" :)));
   if (file_size(_savedir+ "times") > 0)
      _times = restore_variable(unguarded((: read_file,
      _savedir+ "times" :)));
   if (file_size(_savedir+ "list") > 0)
      _list = restore_variable(unguarded((: read_file, _savedir+ "list" :)));
}
/* set_very_short() */

/**
 * Query the very short name of the shop.
 * @see set_very_short()
 * @return the very short name of the shop.
 */
string shop_very_short() { return copy(_very_short); }