diff --git a/src/globals.h b/src/globals.h index 40decff..0a9c12d 100644 --- a/src/globals.h +++ b/src/globals.h @@ -47,7 +47,7 @@ #define MAX_PLAYERS 8 // Maximum number of players #define INITIAL_CASH 6000.00 // Initial cash per player #define MAX_OVERDRAFT 1000.00 // Max. value player can go negative -#define PROB_BANKRUPTCY 0.07 // If overdraft, 7% chance of bankruptcy +#define MAKE_BANKRUPT 0.07 // If overdraft, 7% chance of bankruptcy #define MAX_COMPANIES 8 // Max. number of companies (do not change!) #define INITIAL_STOCK_ISSUED 5 // Initial number of shares issued out @@ -55,34 +55,44 @@ #define INITIAL_SHARE_PRICE 60.00 // Initial share price #define SHARE_PRICE_INC 60.00 // Share price incr. for increase in shipping -#define SHARE_PRICE_INC_OUTPOST 70.00 // Incr. for adding an outpost -#define SHARE_PRICE_INC_OUTSTAR 70.00 // Extra incr. for adding outpost next to star +#define SHARE_PRICE_INC_OUTPOST 75.00 // Incr. for adding an outpost +#define SHARE_PRICE_INC_OUTSTAR 150.00 // Extra incr. for adding outpost next to star #define SHARE_PRICE_INC_STAR 300.00 // Incr. for adding next to star -#define SHARE_PRICE_INC_EXTRA 0.50 // Extra factor when incr. share price +#define PRICE_INC_ADJUST_MIN 0.75 // Actual incr. may be as low as 75% of nominal +#define PRICE_INC_ADJUST_MAX 1.25 // Actual incr. may be as high as 125% +#define MAX_STOCK_RATIO_MIN 0.10 // Min. multiplier to increment available shares +#define MAX_STOCK_RATIO_MAX 0.25 // Max. multiplier, using share price incr. #define MERGE_STOCK_RATIO 0.50 // 50% of old shares are credited to new company -#define COMPANY_BANKRUPTCY 0.01 // 1% chance of company bankruptcy +#define MERGE_BONUS_RATE 10.0 // Multiplier for merger cash bonus +#define MERGE_PRICE_ADJUST_MIN 0.40 // Minimum of old share price used as increment +#define MERGE_PRICE_ADJUST_MAX 0.60 // Maximum of old share price used as increment +#define COMPANY_BANKRUPTCY 0.03 // 3% chance of company bankruptcy (if return < 0) #define ALL_ASSETS_TAKEN 0.20 // 20% chance of assets taken of same -#define INC_SHARE_PRICE 0.30 // 30% chance for increasing share price -#define DEC_SHARE_PRICE 0.65 // 65% x 30% chance of decrementing same +#define CHANGE_SHARE_PRICE 0.35 // 35% chance for changing share price +#define DEC_SHARE_PRICE 0.65 // 65% x 35% chance of decrementing same #define PRICE_CHANGE_RATE 0.25 // Up to 25% of share price is used to incr./decr. #define INITIAL_RETURN 0.05 // Initial return per share: 5% -#define GROWING_RETURN_CHANGE 0.25 // Chance of changing return when company grows -#define GROWING_RETURN_INC 0.60 // 60% chance such change will increase return -#define CHANGE_COMPANY_RETURN 0.40 // Chance of randomly changing return -#define COMPANY_RETURN_INC 0.75 // 75% chance such change will increase return -#define MAX_COMPANY_RETURN 0.40 // Maximum return per share -#define RETURN_DIVIDER 1.50 // Min. amount by which to divide if return too large +#define MIN_COMPANY_RETURN -0.10 // Minimum return per share (yes, negative!) +#define MAX_COMPANY_RETURN 0.20 // Maximum return per share +#define CHANGE_COMPANY_RETURN 0.50 // Chance of randomly changing return +#define DEC_COMPANY_RETURN 0.50 // Chance such change will decrease return +#define RETURN_MAX_CHANGE 0.03 // Maximum that company return will change +#define CHANGE_RETURN_GROWING 0.25 // Chance of changing return when company grows +#define DEC_RETURN_GROWING 0.35 // 35% chance such change will decrement return +#define GROWING_MAX_CHANGE 0.02 // Maximum that that return can change + #define OWNERSHIP_BONUS 2.00 // Bonus amount based on percentage ownership #define BID_CHANCE 0.75 // 75% chance of successful bidding #define MAX_SHARES_BIDDED 200 // Max. number of shares issued #define INITIAL_INTEREST_RATE 0.10 // Initial bank interest rate: 10% -#define CHANGE_INTEREST_RATE 0.30 // 30% chance of changing interest rate -#define INTEREST_RATE_INC 0.65 // 65% chance of above being an increment -#define MAX_INTEREST_RATE 0.30 // Maximum interest rate -#define INTEREST_RATE_DIVIDER 1.50 // Min. amount by which to divide if interest is too high +#define MIN_INTEREST_RATE 0.02 // Minimum interest rate +#define MAX_INTEREST_RATE 0.20 // Maximum interest rate +#define CHANGE_INTEREST_RATE 0.40 // 40% chance of changing interest rate +#define DEC_INTEREST_RATE 0.45 // 40% x 45% chance of decrease the same +#define INTEREST_MAX_CHANGE 0.03 // Maximum that interest rate will change #define CREDIT_LIMIT_RATE 2.00 // Multiplier for credit limit #define ROUNDING_AMOUNT 0.01 // Round off smaller amounts to zero @@ -96,7 +106,7 @@ typedef struct company_info { wchar_t *name; // Company name double share_price; // Share price - double share_return; // Return per share + double share_return; // Return per share (may be negative) long int stock_issued; // Total stock sold to players long int max_stock; // Max. stock that company has bool on_map; // True if company on map diff --git a/src/move.c b/src/move.c index 96089fa..a0dac31 100644 --- a/src/move.c +++ b/src/move.c @@ -786,9 +786,9 @@ void merge_companies (map_val_t a, map_val_t b) assert(bb >= 0 && bb < MAX_COMPANIES); double val_aa = company[aa].share_price * company[aa].stock_issued * - company[aa].share_return; + (1.0 + company[aa].share_return); double val_bb = company[bb].share_price * company[bb].stock_issued * - company[bb].share_return; + (1.0 + company[bb].share_return); double bonus; long int old_stock, new_stock, total_new; @@ -891,9 +891,9 @@ void merge_companies (map_val_t a, map_val_t b) new_stock = (double) old_stock * MERGE_STOCK_RATIO; total_new += new_stock; - bonus = (company[bb].stock_issued == 0) ? 0.0 : - 10.0 * ((double) player[i].stock_owned[bb] - / company[bb].stock_issued) * company[bb].share_price; + bonus = (company[bb].stock_issued == 0) ? 0.0 : MERGE_BONUS_RATE + * ((double) player[i].stock_owned[bb] + / company[bb].stock_issued) * company[bb].share_price; player[i].stock_owned[aa] += new_stock; player[i].stock_owned[bb] = 0; @@ -921,7 +921,9 @@ void merge_companies (map_val_t a, map_val_t b) // Adjust the company records appropriately company[aa].stock_issued += total_new; company[aa].max_stock += total_new; - company[aa].share_price += company[bb].share_price / (randf() + 1.5); + company[aa].share_price += company[bb].share_price + * (randf() * (MERGE_PRICE_ADJUST_MAX - MERGE_PRICE_ADJUST_MIN) + + MERGE_PRICE_ADJUST_MIN); company[bb].stock_issued = 0; company[bb].max_stock = 0; @@ -1001,11 +1003,22 @@ void inc_share_price (int num, double inc) { assert(num >= 0 && num < MAX_COMPANIES); - company[num].share_price += inc * (1.0 + randf() * SHARE_PRICE_INC_EXTRA); - company[num].max_stock += inc / (randf() * 10.0 + 5.0); + company[num].share_price += inc * (randf() + * (PRICE_INC_ADJUST_MAX - PRICE_INC_ADJUST_MIN) + PRICE_INC_ADJUST_MIN); + company[num].max_stock += inc * (randf() + * (MAX_STOCK_RATIO_MAX - MAX_STOCK_RATIO_MIN) + MAX_STOCK_RATIO_MIN); - if (randf() < GROWING_RETURN_CHANGE) { - company[num].share_return *= randf() + GROWING_RETURN_INC; + if (randf() < CHANGE_RETURN_GROWING) { + double change = randf() * GROWING_MAX_CHANGE; + if (randf() < DEC_RETURN_GROWING) { + change = -change; + } + + company[num].share_return += change; + if ( company[num].share_return > MAX_COMPANY_RETURN + || company[num].share_return < MIN_COMPANY_RETURN) { + company[num].share_return -= 2.0 * change; + } } } @@ -1022,7 +1035,7 @@ void adjust_values (void) if (randf() > (1.0 - COMPANY_BANKRUPTCY)) { which = randi(MAX_COMPANIES); - if (company[which].on_map) { + if (company[which].on_map && company[which].share_return <= 0.0) { if (randf() < ALL_ASSETS_TAKEN) { txdlgbox(MAX_DLG_LINES, 60, 6, WCENTER, attr_error_window, attr_error_title, attr_error_highlight, @@ -1045,7 +1058,8 @@ void adjust_values (void) for (int i = 0; i < number_players; i++) { if (player[i].in_game) { - player[i].cash += player[i].stock_owned[which] * rate; + player[i].cash += player[i].stock_owned[which] + * company[which].share_price * rate; } } @@ -1127,19 +1141,21 @@ void adjust_values (void) if (randf() < CHANGE_COMPANY_RETURN) { which = randi(MAX_COMPANIES); if (company[which].on_map) { - company[which].share_return *= randf() + COMPANY_RETURN_INC; - } - } + double change = randf() * RETURN_MAX_CHANGE; + if (randf() < DEC_COMPANY_RETURN) { + change = -change; + } - // Make sure that a company's return is not too large - for (int i = 0; i < MAX_COMPANIES; i++) { - if (company[i].on_map && company[i].share_return > MAX_COMPANY_RETURN) { - company[i].share_return /= randf() + RETURN_DIVIDER; + company[which].share_return += change; + if ( company[which].share_return > MAX_COMPANY_RETURN + || company[which].share_return < MIN_COMPANY_RETURN) { + company[which].share_return -= 2.0 * change; + } } } // Increase or decrease share price - if (randf() < INC_SHARE_PRICE) { + if (randf() < CHANGE_SHARE_PRICE) { which = randi(MAX_COMPANIES); if (company[which].on_map) { double change = randf() * company[which].share_price @@ -1163,12 +1179,35 @@ void adjust_values (void) } } + // Has the player lost money due to negative share returns? + if (player[current_player].cash < 0.0) { + double borrowed = -player[current_player].cash; + + txdlgbox(MAX_DLG_LINES, 60, 7, WCENTER, attr_error_window, + attr_error_title, attr_error_highlight, 0, 0, + attr_error_waitforkey, _(" Interstellar Trading Bank "), + /* xgettext:c-format */ + _("You were forced to borrow %N\n" + "to cover losses from company shares."), + borrowed); + txrefresh(); + + player[current_player].cash = 0.0; + player[current_player].debt += borrowed; + } + // Change the interest rate if (randf() < CHANGE_INTEREST_RATE) { - interest_rate *= randf() + INTEREST_RATE_INC; - } - if (interest_rate > MAX_INTEREST_RATE) { - interest_rate /= randf() + INTEREST_RATE_DIVIDER; + double change = randf() * INTEREST_MAX_CHANGE; + if (randf() < DEC_INTEREST_RATE) { + change = -change; + } + + interest_rate += change; + if ( interest_rate > MAX_INTEREST_RATE + || interest_rate < MIN_INTEREST_RATE) { + interest_rate -= 2.0 * change; + } } // Calculate current player's debt @@ -1198,7 +1237,7 @@ void adjust_values (void) } // Shall we declare them bankrupt? - if (total_value(current_player) <= 0.0 && randf() < PROB_BANKRUPTCY) { + if (total_value(current_player) <= 0.0 && randf() < MAKE_BANKRUPT) { bankrupt_player(true); } }