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/
// Pinkfish
// Started Wed May 30 21:37:15 PDT 2001

inherit "/std/room/furniture/games/card_base";
inherit "/std/room/furniture/games/multiplayer_base";
inherit "/std/room/furniture/commercial";

#include <money.h>

#define BLACKJACK_BET 0
#define BLACKJACK_PLAYING 1
#define BLACKJACK_BUST 2
#define BLACKJACK_STAND 3

class player_data {
   class playing_card* hand;
   int starting_bet;
   int state;
}

#define BOARD_TAG "blackjack"

//
// This gives an estimated return on the payment.  For example 50%
// return would mean you get back approximately 50% of your money on
// average
//
private int _cost;
private int _finished;
private int _max_bet;
private int _min_bet;
private int _timeout_call;
private int _timeout_length;
private int _num_decks;
private int _soft_seventeen;
private int _double_on_doubles;
private class playing_card* _dealer_hand;
private class playing_card* _deck;
private class playing_card* _discard;

int query_hand_value(class playing_card* cards);

void create() {
   multiplayer_base::create();
   commercial::create();
} /* create() */

void setup() {
   set_name( "table" );
   set_short( "blackjack table" );
   add_adjective( ({ "blackjack" } ));
   add_alias("blackjack");
   set_long( "The green felt of the table looks nice and soft, there is "
             "a single deck of cards sitting in the middle of the table.  "
             "The table looks like it will seat 4 people.\n");
   set_allowed_positions(({"sitting", "lying", "kneeling", "meditating"}));
   set_allowed_room_verbs((["sitting" : "sits" ]));
   set_weight(2000);
   set_value(240000);
   // Minimum bid $1.
   _timeout_length = 5 * 60;
   _cost = 400;
   _num_decks = 1;

   add_player_id_type("green", 0);
   add_player_id_type("red", 0);
   add_player_id_type("blue", 0);
   add_player_id_type("maroon", 0);

   set_minimum_needed(1);
   add_help_file("blackjack");

   set_commercial_size(15);
   set_commercial_type("gambling");
   set_shop_use_types(({ "blackjack" }));
}

/**
 * This method shows the current status of the cards.
 * @param id the id to show the status for
 * @return the status of the cards
 */
string query_card_status() {
   string id_bing;
   string ret;
   string* not_playing;
   class player_data data;
   class playing_card card;
   string* womble;
   string place;

   ret = "";
   not_playing = ({ });
   womble = query_player_ids();
   place = environment()->query_property("place");
   foreach (id_bing in womble) {
      if (is_person_playing(id_bing) ||
          is_game_started()) {
         ret += capitalize(id_bing) + " (" +
                query_player_cap_name(id_bing) + ")";
         data = query_player_data(id_bing);
         if (data) {
            if (data->starting_bet) {
               ret += "  " + 
                      MONEY_HAND->money_value_string(data->starting_bet, place);
               if (sizeof(data->hand)) {
                  foreach (card in data->hand) {
                     ret += "  " + query_card_string(card);
                  }
               }
               if (data->state == BLACKJACK_STAND) {
                  ret += " (stand)";
               } else if (data->state == BLACKJACK_BUST) {
                  ret += " (bust)";
               }
               ret += "\n";
            } else {
               ret += "  No bet yet.\n";
            }
         } else {
            ret += "\n";
         }
      } else {
         not_playing += ({ id_bing });
      }
   }

   if (sizeof(not_playing)) {
      ret += query_multiple_short(map(not_playing, (: capitalize($1) :))) +
                               " are not playing.\n";
   }

   ret += "\n";
   if (sizeof(_dealer_hand)) {
      ret += "Dealer's cards ";
      if (!_finished) {
         ret += "XXXX";
      }
      foreach (card in _dealer_hand[(_finished?0:1)..]) {
         ret += "  " + query_card_string(card);
      }
      if (query_hand_value(_dealer_hand) > 21) {
         ret += " (bust)";
      }
      ret += "\n";
   }

   return ret;
}
   
/** @ignore yes */
string long(string str, int dark) {
   if (dark) {
      return ::long() +
             "It is too dark to make out the pieces on the board.\n";
   }
   return ::long() + query_card_status();
} /* long() */

/**
 * This method returns the next card from the deck.
 * @return the next card from the deck
 */
class playing_card query_next_card() {
   class playing_card card;

   if (!sizeof(_deck)) {
      if (!sizeof(_discard)) {
         _deck = make_deck(_num_decks, 0);
         _deck = shuffle_deck(_deck);
      } else {
         _deck = make_deck(_num_decks, 0);
         _deck = shuffle_deck(_deck);
         //_deck = shuffle_deck(_discard);
      }
      tell_all_players("The dealer shuffles the deck before the next card "
                       "is dealt.\n");
      _discard = ({});
   }
   card = _deck[0];
   _deck = _deck[1..];
   return card;
} /* query_next_card() */

/**
 * This deals cards to everyone.
 */
void deal_cards(string id) {
   class player_data data;
   string hands;

   if (!sizeof(_dealer_hand)) {
      _dealer_hand = ({ query_next_card(), query_next_card() });
   }
   // Everyone gets one card...
   hands = "";
   //foreach (id in query_currently_playing_ids()) {
      data = query_player_data(id);
      data->hand = ({ query_next_card(), query_next_card() });
      hands += query_player_cap_name(id) + " hand is: "+
                      query_card_string(data->hand[0]) + "  " +
                      query_card_string(data->hand[1]) +
                      "  (total " +
                      query_hand_value(data->hand) + ")\n";
   //}
   hands += "Dealer's cards: XXXX " +
             query_card_string(_dealer_hand[0]) + "\n"
             "You need to stay or hit yourself for more cards.\n";
   tell_all_players(hands);
} /* deal_cards() */

/** @ignore yes */
int start_game() {
   class player_data data;
   string id;

   randomise_player_numbers();
   if (!::start_game()) {
      return 0;
   }
   foreach (id in query_player_ids()) {
      data = new(class player_data);
      data->starting_bet = 0;
      data->hand = ({ });
      data->state = BLACKJACK_BET;
      set_player_data(id, data);
   }
   _dealer_hand = ({ });
   _finished = 0;
   //redeal_cards();
   tell_all_players("Place your starting bets.\n");
   return 1;
} /* reset_game() */

/**
 * This figures out the value of the cards.
 * @param cards the crds to check
 * @return the value of the hand
 */
int query_hand_value(class playing_card* cards) {
   class playing_card bing;
   int value;
   int no_aces;

   foreach (bing in cards) {
      if (bing->number == 1) {
         no_aces++;
      } else if (bing->number >= 10) {
         value +=  10;
      } else {
         value += bing->number;
      }
   }

   if (no_aces > 0) {
      if (no_aces > 1) {
         value += no_aces - 1;
      }
      if (value <= 10) {
         value += 11;
      } else {
         value += 1;
      }
   }

   return value;
} /* query_hand_value() */

/**
 * This figures out if the value is a 'soft' one of the specified type.
 * @param cards the crds to check
 * @return 1 if it is a soft result or not
 */
int is_soft_result(class playing_card* cards) {
   class playing_card bing;
   int value;
   int no_aces;

   foreach (bing in cards) {
      if (bing->number == 1) {
         no_aces++;
      } else if (bing->number >= 10) {
         value +=  10;
      } else {
         value += bing->number;
      }
   }

   if (no_aces > 0) {
      if (no_aces > 1) {
         value += no_aces - 1;
      }
      if (value <= 10) {
         return 1;
      }
   }

   return 0;
} /* query_hand_value() */

/**
 * Checks to see if all the people playing have put in their first
 * bets.
 */
void finish_bet(string id) {
   //string id;
   class player_data data;

   data = query_player_data(id);
   // Move to the next state!
   call_out("deal_cards", 2, id);
} /* check_for_finish_bet() */

void complete_round() {
   int value;
   string stuff;
   object ob;
   int new_value;
   class playing_card card;
   class player_data data;
   string id;
   string place;
   int paid;
   string* winners;
   string* losers;

   remove_call_out(_timeout_call);
   _timeout_call = 0;
   place = environment()->query_property("place");
   value = query_hand_value(_dealer_hand);
   while (value < 17 ||
          (value == 17 && _soft_seventeen && is_soft_result(_dealer_hand))) {
      _dealer_hand += ({ query_next_card() });
      value = query_hand_value(_dealer_hand);
   }


   stuff = "";
   foreach (card in _dealer_hand) {
      stuff += "  " + query_card_string(card);
   }
   if (value > 21) {
      stuff += "  Total " + value + " (bust)\n";
      value = 0;
   } else {
      stuff += "  Total " + value + "\n";
   }
   winners = ({ });
   losers = ({ });
   foreach (id in query_currently_playing_ids()) {
      data = query_player_data(id);
      if (data->state == BLACKJACK_STAND) {
         new_value = query_hand_value(data->hand);
         if (new_value == 21 && sizeof(data->hand) == 2) {
            winners += ({ id });
            // They get a pay out.
            ob = query_player_object(id);
            if (ob) {
               ob->adjust_money(MONEY_HAND->create_money_array((data->starting_bet * 5) / 2,
                                           place), place);
            }
            //_pay_out += (data->starting_bet * 3) / 2;
            //_revenue -= data->starting_bet;
            adjust_float(-(data->starting_bet * 3) / 2);
            if (ob) {
               stuff += ob->query_cap_name();
            } else {
               stuff += id;
            }
            stuff += " gets a payout of " +
                     MONEY_HAND->money_value_string((data->starting_bet * 3) / 2, place) +
                     " (plus their original money back).\n";
            paid = 1;
         } else if (new_value > value) {
            winners += ({ id });
            // They get a pay out.
            ob = query_player_object(id);
            if (ob) {
               ob->adjust_money(MONEY_HAND->create_money_array(data->starting_bet * 2,
                                           place), place);
            }
            //_pay_out += data->starting_bet;
            //_revenue -= data->starting_bet;
            adjust_float(-data->starting_bet);
            if (ob) {
               stuff += ob->the_short();
            } else {
               stuff += id;
            }
            stuff += " gets a payout of " +
                     MONEY_HAND->money_value_string(data->starting_bet, place) +
                     " (plus their original money back).\n";
            paid = 1;
         } else {
            losers += ({ id });
         }
      }
   }
   if (!paid) {
      stuff += "No one gets paid anything.\n";
   }
   // Do the dealer.
   tell_all_players("The dealer reveals their cards as " +
                    stuff);
   if (sizeof(winners)) {
      tell_room(environment(),
                query_multiple_short(winners) + " win" +
                (sizeof(winners) > 1?"":"s") + " the blackjack hand.\n");
   } else {
      tell_room(environment(),  "No one wins the blackjack hand.\n");
   }

   finish_game(0);
   _finished = 1;
} /* complete_round() */

void force_finish() {
   if (is_game_started()) {
      complete_round();
   }
} /* force_finish() */

/**
 * Places your bet.
 */
int do_bet(string str) {
   string place;
   string id;
   int amount;
   class player_data data;

   if (!is_game_started()) {
      add_failed_mess("The game has not started.\n");
      return 0;
   }

   id = find_player_id_of_person(this_player());
   if (!id) {
      add_failed_mess("You are not playing.\n");
      return 0;
   }

   place = environment()->query_property("place");

   amount = MONEY_HAND->value_from_string(str, place);
   if (!amount) {
      add_failed_mess("Invalid bet amount.\n");
      return 0;
   }
   if (this_player()->query_value_in(place) < amount) {
      add_failed_mess("You do not have that much to bid.\n");
      return 0;
   }

   if (amount < _min_bet) {
      add_failed_mess("The minimum bet for $D is " +
         MONEY_HAND->money_value_string(_min_bet, place) + ".\n");
      return 0;
   }
   if (amount > _max_bet) {
      add_failed_mess("The maximum bet for $D is " +
         MONEY_HAND->money_value_string(_max_bet, place) + ".\n");
      return 0;
   }

   data = query_player_data(id);
   if (data->starting_bet) {
      add_failed_mess("You have already bet on $D.\n");
      return 0;
   }
   this_player()->pay_money(MONEY_HAND->create_money_array(amount, place),
                            place);

   //_revenue += amount;
   adjust_float(amount);

   // This is for the starting bet.
   data->starting_bet = amount;
   data->state = BLACKJACK_PLAYING;
   finish_bet(id);
   add_succeeded_mess("$N $V " +
                      MONEY_HAND->money_value_string(amount, place) +
                      " on $D.\n");
   return 1;
} /* do_bet() */

/**
 * This hits you for another card.
 */
int do_hit() {
   int value;
   int not_done;
   string id;
   class player_data data;
   class playing_card card;

   // Get another card.
   if (!is_game_started()) {
      add_failed_mess("The game has not started.\n");
      return 0;
   }

   id = find_player_id_of_person(this_player());
   if (!id) {
      add_failed_mess("You are not playing.\n");
      return 0;
   }

   data = query_player_data(id);

   if (data->state != BLACKJACK_PLAYING) {
      add_failed_mess("You are out of the game and cannot get any more "
                      "cards.\n");
      return 0;
   }

   if (!sizeof(data->hand)) {
      add_failed_mess("You cannot hit before you have been dealt cards.\n");
      return 0;
   }

   card = query_next_card();
   data->hand += ({ card });
   value = query_hand_value(data->hand);
   if (value > 21) {
      add_succeeded_mess("$N $V and get$s " + query_card_string(card) +
                         " giving a total of " + value +
                         " and going bust on $D.\n");
      data->state = BLACKJACK_BUST;
      foreach (id in query_currently_playing_ids()) {
         data = query_player_data(id);
         if (data->state != BLACKJACK_BUST &&
             data->state != BLACKJACK_STAND) {
            not_done = 1;
         }
      }
      if (!not_done) {
          remove_call_out(_timeout_call);
          _timeout_call = call_out("complete_round", 2);
      }
   } else {
      add_succeeded_mess("$N $V and gets " + query_card_string(card) +
                         " giving a total of " + value + " on $D.\n");
   }
   return 1;
} /* do_hit() */

int do_stand() {
   int value;
   string id;
   class player_data data;
   int not_done;

   // Get another card.
   if (!is_game_started()) {
      add_failed_mess("The game has not started.\n");
      return 0;
   }

   id = find_player_id_of_person(this_player());
   if (!id) {
      add_failed_mess("You are not playing.\n");
      return 0;
   }

   data = query_player_data(id);

   if (data->state != BLACKJACK_PLAYING) {
      add_failed_mess("You are not playing and set yourself to stand.\n");
      return 0;
   }

   value = query_hand_value(data->hand);

   data->state = BLACKJACK_STAND;
   foreach (id in query_currently_playing_ids()) {
      data = query_player_data(id);
      if (data->state != BLACKJACK_BUST &&
          data->state != BLACKJACK_STAND) {
         not_done = 1;
      }
   }
   if (!not_done) {
       remove_call_out(_timeout_call);
       _timeout_call = call_out("complete_round", 2);
   }
   add_succeeded_mess("$N $V with a total of " + value +
                      " on $D.\n");
   return 1;
} /* do_stand() */

/**
 * Starts a nice furry game.
 */
int do_start() {
   if (!is_open_for("blackjack", this_player()->query_name())) {
      add_failed_mess("The blackjack table is not open.\n");
      return 0;
   }

   if (_timeout_call) {
      add_failed_mess("Someone is still playing, you cannot start a "
                      "new game yet.\n");
      return 0;
   }

   //
   // There must eb enough money in the float for everyone to bid the max amo
   // amount and win with a blackjack.
   //
   if (query_float() < (_max_bet * 3 * 4) / 2) {
      if (is_allowed(this_player()->query_name())) {
         add_failed_mess("The float is too low for the table to open.\n");
         return 0;
      }
      add_failed_mess("The blackjack table is not open.\n");
      return 0;
   }

   if (!is_playing(this_player())) {
      add_failed_mess("You must be playing the game to start it.\n");
      return 0;
   }

   if (!start_game()) {
      add_failed_mess("You need at least three people to play modern art.\n");
      return 0;
   }

   add_succeeded_mess("$N $V a game on $D.\n");
   remove_call_out(_timeout_call);
   _timeout_call = call_out("force_finish", _timeout_length);
   tell_all_players("Timeout for this game is " + (_timeout_length / 60) +
                    " minutes.\n");
   return 1;
} /* do_start() */

/**
 * If it is finished early...  Oh dear.
 */
int do_finish() {
   string person;

   if (!is_game_started()) {
      add_failed_mess("The game has not started.\n");
      return 0;
   }

   person = find_player_id_of_person(this_player());
   if (!person) {
      add_failed_mess("You must actually be playing to finish the game.\n");
      return 0;
   }

   force_finish();
   return 1;
} /* do_finish() */

string query_main_status(int hint) {
   string place;
   string ret;

   place = query_money_place();
   ret = "$I$0=Blackjack table:\n"
          "$I$6=   Table is " +
             (query_float() >= (_max_bet * 3 * 4) / 2?"open.\n":
              "closed! (Float needed: " +
              MONEY_HAND->money_value_string((_max_bet * 3 * 4) / 2, place) +
              "; current: " +
              MONEY_HAND->money_value_string(query_float(), place) + ")\n") +
          "$I$6=   Timeout length: " + (_timeout_length / 60) + " minutes.\n";
   if (hint) {
      ret += "$I$6=      set timeout <number> on <table>\n";
   }
   ret += "$I$6=   Maximum bet: " +
              MONEY_HAND->money_value_string(_max_bet, place) + "\n";
   if (hint) {
      ret += "$I$6=      set maximum bet <amount> on <table>\n";
   }
   ret += "$I$6=   Minimum bet: " +
              MONEY_HAND->money_value_string(_min_bet, place) + "\n";
   if (hint) {
      ret += "$I$6=      set minimum bet <amount> on <table>\n";
   }
   ret += "$I$6=   Num Decks  : " + _num_decks + "\n";
   if (hint) {
      ret += "$I$6=      set num decks <amount> on <table>\n";
   }
   ret += "$I$6=   Soft 17    : " + (_soft_seventeen?"on":"off") + "\n";
   if (hint) {
      ret += "$I$6=      set hit on soft seventeen {on|off} on <table>\n";
   }
/*
   ret += "$I$6=   Doubles    : " + (_double_on_doubles?"on":"off") + "\n";
   if (hint) {
      ret += "$I$6=      set doubles {on|off} on <table>\n";
   }
 */
   ret += "$I$6=   Float needed: " +
              MONEY_HAND->money_value_string((_max_bet * 3 * 4) / 2, place) +
          " (max players * max bet * 3 / 2)\n$I$6=   Revenue: " +
          MONEY_HAND->money_value_string(query_revenue(), place) +
          "\n\n";
   return ret;
} /* query_main_status() */

/**
 * This method sets the bet boundaries.
 * @param str the amount string
 * @param max_bet if it a max or min bet to set
 */
int do_set_bet(string str, int max_bet) {
   string place;
   int value;

   if (!is_allowed(this_player()->query_name())) {
      add_failed_mess("You are not allowed to change the paramaters of "
                   "$D.\n");
      return 0;
   }
   place = query_money_place();
   value = MONEY_HAND->value_from_string(str, place);
   if (!value) {
      add_failed_mess("Unable to parse the string " + str + ".\n");
      return 0;
   }
   if (max_bet) {
      _max_bet = value;
      add_succeeded_mess("$N set$s the maximum bet to " +
          MONEY_HAND->money_value_string(value, place) + " on $D.\n");
   } else {
      _min_bet = value;
      add_succeeded_mess("$N set$s the minimum bet to " +
          MONEY_HAND->money_value_string(value, place) + " on $D.\n");
   }

   return 1;
} /* do_set_bet() */

/**
 * This method sets the timeout for the table.
 */
int do_set_timeout(int length) {
   if (!is_allowed(this_player()->query_name())) {
      add_failed_mess("You are not allowed to change the paramaters of "
                   "$D.\n");
      return 0;
   }

   if (length <= 0) {
      add_failed_mess("The timeout must be greator than 0.\n");
      return 0;
   }
   _timeout_length = length * 60;
   add_succeeded_mess("$N set$s the timeout on $D to " + length + " minutes.\n");
   return 1;
} /* do_set_timeout() */

/**
 * This method sets the soft_seventeen for the table.
 */
int do_set_soft_seventeen(int value) {
   if (!is_allowed(this_player()->query_name())) {
      add_failed_mess("You are not allowed to change the paramaters of "
                   "$D.\n");
      return 0;
   }

   _soft_seventeen = value;
   add_succeeded_mess("$N set$s the soft seventeen dealer hit on $D " +
                      (value?"on":"off") + ".\n");
   return 1;
} /* do_set_soft_seventeen() */

/**
 * This method sets the soft_seventeen for the table.
 */
int do_set_double_on_doubles(int value) {
   if (!is_allowed(this_player()->query_name())) {
      add_failed_mess("You are not allowed to change the paramaters of "
                   "$D.\n");
      return 0;
   }

   _double_on_doubles = value;
   add_succeeded_mess("$N set$s the double on doubles on $D " +
                      (value?"on":"off") + ".\n");
   return 1;
} /* do_set_double_on_doubles() */

/**
 * This method sets the timeout for the table.
 */
int do_set_num_decks(int num_decks) {
   if (!is_allowed(this_player()->query_name())) {
      add_failed_mess("You are not allowed to change the paramaters of "
                   "$D.\n");
      return 0;
   }

   if (num_decks <= 0) {
      add_failed_mess("The timeout must be greator than 0.\n");
      return 0;
   }
   if (num_decks >= 10) {
      add_failed_mess("The number of decks must be less than 10.\n");
      return 0;
   }
   _num_decks = num_decks;
   add_succeeded_mess("$N set$s the number of decks on $D to " + num_decks +
                      ".\n");
   return 1;
} /* do_set_num_decks() */

void init() {
   multiplayer_base::init();
   commercial::init();
   add_command("bet", "<string'amount'> on <direct:object>",
               (: do_bet($4[0]) :));
   add_command("hit", "on <direct:object>",
               (: do_hit() :));
   add_command("stay", "on <direct:object>",
               (: do_stand() :));
/*
   add_command("finish", "game on <direct:object>",
               (: do_finish() :));
 */
   add_command("start", "[new] game on <direct:object>",
               (: do_start() :));

   if (environment()->is_allowed(this_player()->query_name())) {
      add_command("set", "minimum bet <string'amount'> on <direct:object>",
                  (: do_set_bet($4[0], 0) :));
      add_command("set", "maximum bet <string'amount'> on <direct:object>",
                  (: do_set_bet($4[0], 1) :));
      add_command("set", "timeout <number'minutes'> on <direct:object>",
                  (: do_set_timeout($4[0]) :));
      add_command("set", "num decks <number'num decks'> on <direct:object>",
                  (: do_set_num_decks($4[0]) :));
/*
      add_command("set", "double on doubles {on|off} on <direct:object>",
                  (: do_set_double_on_doubles($4[0] == "on") :));
 */
      add_command("set", "hit on soft seventeen {on|off} on <direct:object>",
                  (: do_set_soft_seventeen($4[0] == "on") :));
   }
} /* init() */

/** @ignore yes */
mapping query_dynamic_auto_load() {
   mapping map;

   map = commercial::query_dynamic_auto_load();
   multiplayer_base::query_dynamic_auto_load(map);
   //add_auto_load_value(map, BOARD_TAG, "return", _return);
   add_auto_load_value(map, BOARD_TAG, "cost", _cost);
   //add_auto_load_value(map, BOARD_TAG, "pay out", _pay_out);
   //add_auto_load_value(map, BOARD_TAG, "revenue", _revenue);
   add_auto_load_value(map, BOARD_TAG, "dealer hand", _dealer_hand);
   add_auto_load_value(map, BOARD_TAG, "deck", _deck);
   add_auto_load_value(map, BOARD_TAG, "discard", _discard);
   add_auto_load_value(map, BOARD_TAG, "finished", _finished);
   add_auto_load_value(map, BOARD_TAG, "max bet", _max_bet);
   add_auto_load_value(map, BOARD_TAG, "min bet ", _min_bet);
   add_auto_load_value(map, BOARD_TAG, "timeout", _timeout_length);
   add_auto_load_value(map, BOARD_TAG, "num decks", _num_decks);
   add_auto_load_value(map, BOARD_TAG, "soft seventeen", _soft_seventeen);
   add_auto_load_value(map, BOARD_TAG, "double on doublet", _double_on_doubles);
   return map;
} /* query_dynamic_auto_load() */

/** @ignore yes */
void init_dynamic_arg(mapping map, object player) {
   commercial::init_dynamic_arg(map, player);
   multiplayer_base::init_dynamic_arg(map, player);

   //_return = query_auto_load_value(map, BOARD_TAG, "return");
   _cost = query_auto_load_value(map, BOARD_TAG, "cost");
   //_pay_out = query_auto_load_value(map, BOARD_TAG, "pay out");
   //_revenue = query_auto_load_value(map, BOARD_TAG, "revenue");
   _dealer_hand = query_auto_load_value(map, BOARD_TAG, "dealer hand");
   _deck = query_auto_load_value(map, BOARD_TAG, "deck");
   _discard = query_auto_load_value(map, BOARD_TAG, "discard");
   _finished = query_auto_load_value(map, BOARD_TAG, "finished");
   _min_bet = query_auto_load_value(map, BOARD_TAG, "min bet");
   _max_bet = query_auto_load_value(map, BOARD_TAG, "max bet");
   _timeout_length = query_auto_load_value(map, BOARD_TAG, "timeout");
   _num_decks = query_auto_load_value(map, BOARD_TAG, "num decks");
   _soft_seventeen = query_auto_load_value(map, BOARD_TAG, "soft seventeen");
   _double_on_doubles = query_auto_load_value(map, BOARD_TAG, "double on doublet");

   if (!_num_decks) {
      _num_decks = 1;
   }

   if (is_game_started()) {
      remove_call_out(_timeout_call);
      _timeout_call = call_out("force_finish", _timeout_length);
   }
} /* init_dynamic_arg() */