1
0
mirror of https://git.zap.org.au/git/trader.git synced 2024-10-27 18:20:13 -04:00

Revise the game algorithms extensively

In summary: share returns can now be negative, decreasing a player's
income; the bank interest rate now has a minimum; algorithms for changing
share price, share return and bank interest rate are much "smoother" (as
modelled with Gnuplot!); many minimum, maximum and typical values have
been revised.
This commit is contained in:
John Zaitseff 2012-03-27 10:13:57 +11:00
parent c1c580c133
commit 35abce5052
2 changed files with 92 additions and 43 deletions

View File

@ -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

View File

@ -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);
}
}