/** * A Room Rental Handler * <p> * This keeps track of who rented what rooms where * and for how much. * <p> * After including <room/room_rental.h> there are two options * available for room inherits. ROOM_RENTAL_INHERIT_BASIC_ROOM * includes the basic room inherit while ROOM_RENTAL_INHERIT_ROOM * is for use in areas that have their own base room inherits. * <p> * The most important function is the one that checks that someone * is allowed to enter. * <br> * int check_entry( object player, object room ) * <br> * it returns: * RENTAL_SUCCESS if the player rents the room successfully * RENTAL_NO_SUCH_ROOM if the room isn't on the books * RENTAL_ALREADY_RENTED if the room is rented to someone else * RENTAL_AVAILABLE if the player doesn't rent the room but it is available * * @author goldenthread * @started 3 Sep y2k1 * */ #include <money.h> #include <room/room_rental.h> protected void do_load(); protected void do_save(); protected void evict_tenant( object room_ob ); private nosave int loaded = 0; private mapping rented_rooms = ([]); private mapping rental = ([]); private mapping eviction_times = ([]); private mapping locations = ([]); /* maps room shorts to paths */ private mapping paths = ([]); /** @ignore yes */ void create() { do_load(); } /* create() */ /** @ignore yes */ void reset() { string room; int now = time(); foreach( room in keys( rented_rooms ) ) { if ( stringp( rented_rooms[ room ] ) ) { if ( ( eviction_times[ room ] < now ) && ( eviction_times[ room ] > -1 ) ) { /* chuck out the tenant! */ evict_tenant( find_object( room ) ); tell_creator( "goldenthread", "RENTAL: %s no longer rents %s\n", rented_rooms[ room ], room ); rented_rooms[ room ] = 0; eviction_times[ room ] = -1; } } } do_save(); } /* reset() */ /** @ignore yes */ protected void do_load() { if ( !loaded ) unguarded( (: restore_object( ROOM_RENTAL_SAVE_FILE, 1 ) :) ); loaded = 1; } /* do_load */ /** @ignore yes */ protected void do_save() { unguarded( (: save_object( ROOM_RENTAL_SAVE_FILE , 0 ) :) ); } /* do_save */ /** * Evicts the tenant ( and guests ). * * @param room_ob the room object */ void evict_tenant( object room_ob ) { object *occupants; occupants = filter( all_inventory( room_ob ), (: living :) ); room_ob->evict_tenant( occupants ); } /** * Adds a room to the handler with a rental cost. * * @see delete_room() * * @param room the path of the room to add to the handler * @param cost the rental cost per day of this room * @param office the current office * * @example * add_room( "/w/goldenthread/workroom", 1000000 ) */ int add_room( string room, int cost, object office ) { object room_ob; if( !room_ob = load_object( room ) ) return 0; rented_rooms[ room ] = 0; rental[ room ] = cost; eviction_times[ room ] = -1; locations[ room ] = office->query_location(); paths[ room_ob->short() ] = room; do_save(); return 1; } /* add_room */ /** * Returns the name of whoever is renting the room specified. * * @param room the short of the room you want to check * @param office the current office * * @return the short of the player who's renting the room */ string query_who_rents( string room, object office ) { if ( locations[room] == office->query_location() ) { if ( stringp( rented_rooms[room] ) ) return rented_rooms[room]; else return "nobody"; } else return "no such room in this location"; } /* query_who_rents */ /** * Checks if a particular player is renting a particular room. * * @param player_ob the player object who you think might be renting the room * @param room_ob the room object that you think the player might be renting * * @return value dependent on success of check. See below for details * * @main * returns: * RENTAL_SUCCESS if the player rents the room successfully * RENTAL_NO_SUCH_ROOM if the room isn't on the books * RENTAL_ALREADY_RENTED if the room is rented to someone else * RENTAL_AVAILABLE if the player doesn't rent the room but it is available */ int check_tenant( object player_ob, object room_ob, object office ) { string player = player_ob->short(); string room = room_ob->short(); if ( player == query_who_rents( room, office ) ) return RENTAL_SUCCESS; else if ( player == "nobody" ) return RENTAL_AVAILABLE; else if ( player == "no such room!" ) return RENTAL_NO_SUCH_ROOM; else return RENTAL_ALREADY_RENTED; } /* check_tenant */ /** * Deletes a room from the handler * * @see add_room() * * @param room the path of the room that will be deleted from the handler * @param office the current office * * @return 0 on success, 1 on failure */ int delete_room( string room, object office ) { string room_short = load_object( room )->short(); if ( locations[room] == office->query_location() ) { map_delete( rented_rooms, room ); map_delete( rental, room ); map_delete( eviction_times, room ); map_delete( locations, room ); map_delete( paths, room_short ); do_save(); return 1; } else return 0; } /* delete_room */ /** * Clears the list of rooms available for rent. * * @param office the current office * * WARNING: This clears all rooms bookable from this office. */ int clear_rooms( object office ) { object room_ob; foreach( string room in keys( filter( locations, (: $2 == $( office->query_location() ) :) ) ) ) { room_ob = load_object( room ); map_delete( rented_rooms, room ); map_delete( rental, room ); map_delete( eviction_times, room ); map_delete( locations, room ); map_delete( paths, room_ob->query_short() ); } do_save(); return 1; } /* clear_rooms */ /** * Returns a list of rooms available in a particular location. * * @return a string ready for presentation to a player containing a * list of all rooms available in that office. * * @param office the office */ string *query_rooms_to_rent( object office ) { return keys( filter( locations, (: $2 == $( office->query_location() ) :) ) ); } /* query_rooms_to_rent */ /** * Handles the actual renting of the room. If the prospective * tenant is already renting the room, it extends the rental. * * @see remove_rental() * * @param player_ob the player who is renting the room * @param room_short the short of the room that is to be rented * @param office the current office * * @return value dependent on success of rental. See below for details * * @main * returns: * RENTAL_SUCCESSFUL if the rental is successful * RENTAL_NO_SUCH_ROOM if the room isn't on the books * RENTAL_ALREADY_RENTED if someone else is renting the room already * RENTAL_NO_MONEY if the player hasn't enough money */ int do_rental( object player_ob, string room_short, object office ) { int result; string domain = office->query_domain(); string room = paths[ room_short ]; /* is the room available for rent */ if ( locations[room] == office->query_location() ) { if ( !rented_rooms[room] || ( rented_rooms[room] == player_ob->short()) ) { if ( (int)player_ob->query_value_in( domain ) < rental[room] ) return RENTAL_NO_MONEY; rented_rooms[room] = player_ob->short(); eviction_times[room] = time() + ONE_DAY; result = RENTAL_SUCCESS; } else result = RENTAL_ALREADY_RENTED; } else result = RENTAL_NO_SUCH_ROOM; do_save(); return result; } /* do_rental() */ /** * Returns the amount needed to pay for a rental * * @param room the room being queried * @return rental amount */ int query_rental_value( string room ) { return rental[ room ]; } /* query_rental_value() */ /** * Removes the rented status from a room. Should be called when the * time limit of the rental is over. * * @see do_rental() * * @param room_ob the room object that is currently rented * * @return 0 on success, 1 on failure */ int remove_rental( object room_ob ) { int result; string room_short = room_ob->short(); string room = paths[ room_short ]; if ( !undefinedp( rented_rooms[room] ) ) { rented_rooms[room] = 0; result = RENTAL_SUCCESS; } else result = RENTAL_NO_SUCH_ROOM; do_save(); return result; } /* remove_rental() */