1
0
Fork 0
trader/src/exch.c

834 lines
26 KiB
C

/************************************************************************
* *
* Star Traders: A Game of Interstellar Trading *
* Copyright (C) 1990-2024, John Zaitseff *
* *
************************************************************************/
/*
Author: John Zaitseff <J.Zaitseff@zap.org.au>
$Id$
This file, exch.c, contains the implementation of functions dealing
with the Interstellar Stock Exchange and Trading Bank as used in Star
Traders.
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/.
*/
#include "trader.h"
/************************************************************************
* Module-specific function prototypes *
************************************************************************/
/*
Function: visit_bank - Visit the Interstellar Trading Bank
Parameters: (none)
Returns: (nothing)
This function allows the current player to borrow or repay money from
the Interstellar Trading Bank.
*/
static void visit_bank (void);
/*
Function: trade_shares - Buy and sell shares in a particular company
Parameters: num - Company with which to trade
bid_used - Has the player used up their bid?
Returns: (nothing)
This function allows the current player to buy and sell shares in
company num. The variable *bid_used is set to true if the player tries
to bid for more shares to be released by the company (whether or not
that bid was successful).
*/
static void trade_shares (int num, bool *bid_used);
/************************************************************************
* Stock Exchange function definitions *
************************************************************************/
// This function is documented in the file "exch.h"
/***********************************************************************/
// exchange_stock: Visit the Interstellar Stock Exchange
void exchange_stock (void)
{
selection_t selection = SEL_NONE;
bool bid_used = false;
bool all_off_map;
int w, i, line;
if (quit_selected || abort_game || ! player[current_player].in_game) {
return;
}
newtxwin(16, WIN_COLS, 1, WCENTER, false, 0);
w = getmaxx(curwin);
while (selection != SEL_EXIT) {
selection = SEL_NONE;
// Display (or refresh) the Stock Exchange window
wbkgdset(curwin, attr_normal_window);
werase(curwin);
box(curwin, 0, 0);
center(curwin, 1, 0, attr_title, 0, 0, 1,
_(" Interstellar Stock Exchange "));
center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1,
_("Player: ^{%ls^}"), player[current_player].name);
all_off_map = true;
for (i = 0; i < MAX_COMPANIES; i++) {
if (company[i].on_map) {
all_off_map = false;
break;
}
}
if (all_off_map) {
center(curwin, 8, 0, attr_normal, attr_highlight, 0, 1,
_("No companies on the map"));
} else {
mvwhline(curwin, 4, 2, ' ' | attr_subtitle, w - 4);
mvwhline(curwin, 5, 2, ' ' | attr_subtitle, w - 4);
left(curwin, 4, 4, attr_subtitle, 0, 0, 2,
/* TRANSLATORS: "Company" is a two-line column label in
a table containing a list of companies. */
pgettext("subtitle", " \nCompany"));
right(curwin, 4, w - 4, attr_subtitle, 0, 0, 2,
/* TRANSLATORS: "Shares left" is a two-line column
label in a table containing the number of shares
left to be purchased in any given company. The
maximum column width is 10 characters (see
STOCK_LEFT_COLS in src/intf.h). */
pgettext("subtitle", "Shares\nleft"));
right(curwin, 4, w - 6 - STOCK_LEFT_COLS, attr_subtitle, 0, 0, 2,
/* TRANSLATORS: "Shares issued" is a two-line column
label in a table containing the number of shares
already sold (ie, bought by all players) in any
given company. The maximum column width is 10
characters (see STOCK_ISSUED_COLS in src/intf.h). */
pgettext("subtitle", "Shares\nissued"));
right(curwin, 4, w - 8 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS,
attr_subtitle, 0, 0, 2,
/* TRANSLATORS: "Return" is a two-line column label in
a table containing the share return as a percentage
in any given company. The maximum column width is
10 characters (see SHARE_RETURN_COLS in src/intf.h). */
pgettext("subtitle", "Return\n(%%)"));
right(curwin, 4, w - 10 - STOCK_LEFT_COLS - STOCK_ISSUED_COLS
- SHARE_RETURN_COLS, attr_subtitle, 0, 0, 2,
/* TRANSLATORS: "Price per share" is a two-line column
label in a table containing the price per share in
any given company. %ls is the currency symbol in
the current locale. The maximum column width is 12
characters INCLUDING the currency symbol (see
SHARE_PRICE_COLS in src/intf.h). */
pgettext("subtitle", "Price per\nshare (%ls)"),
currency_symbol);
for (line = 6, i = 0; i < MAX_COMPANIES; i++) {
if (company[i].on_map) {
left(curwin, line, 2, attr_choice, 0, 0, 1, "%lc",
(wint_t) PRINTABLE_MAP_VAL(COMPANY_TO_MAP(i)));
left(curwin, line, 4, attr_normal, 0, 0, 1, "%ls",
company[i].name);
right(curwin, line, w - 2, attr_normal, 0, 0, 1, "%'ld ",
company[i].max_stock - company[i].stock_issued);
right(curwin, line, w - 4 - STOCK_LEFT_COLS, attr_normal,
0, 0, 1, "%'ld ", company[i].stock_issued);
right(curwin, line, w - 6 - STOCK_LEFT_COLS
- STOCK_ISSUED_COLS, attr_normal, 0, 0, 1, "%.2f ",
company[i].share_return * 100.0);
right(curwin, line, w - 8 - STOCK_LEFT_COLS
- STOCK_ISSUED_COLS - SHARE_RETURN_COLS, attr_normal,
0, 0, 1, " %!N ", company[i].share_price);
line++;
}
}
}
wrefresh(curwin);
// Show menu of choices for the player
newtxwin(7, WIN_COLS, 17, WCENTER, true, attr_normal_window);
left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1,
_("^{<1>^} Display stock portfolio"));
left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1,
/* TRANSLATORS: Each label may be up to 37 characters wide
(for <1> and <2>) or 38 characters wide (for <3> and <4>). */
_("^{<2>^} Display galaxy map"));
left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1,
_("^{<3>^} Visit the Trading Bank"));
left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1,
_("^{<4>^} Exit the Stock Exchange"));
center(curwin, 1, -1, attr_normal, attr_keycode, attr_highlight, 1,
_("Enter selection [^[Company letter^]/^{1^}-^{4^}]: "));
curs_set(CURS_ON);
wrefresh(curwin);
// Get the actual selection made by the player
while (selection == SEL_NONE) {
wint_t key;
if (gettxchar(curwin, &key) == OK) {
// Ordinary wide character
bool found;
if (iswupper(*keycode_company)) {
key = towupper(key);
} else if (iswlower(*keycode_company)) {
key = towlower(key);
}
for (i = 0, found = false; keycode_company[i] != L'\0'; i++) {
if (keycode_company[i] == (wchar_t) key) {
found = true;
if (company[i].on_map) {
selection = (selection_t) i;
} else {
beep();
}
break;
}
}
if (! found) {
switch (key) {
case L'1':
curs_set(CURS_OFF);
show_status(current_player);
curs_set(CURS_ON);
break;
case L'2':
curs_set(CURS_OFF);
show_map(true);
curs_set(CURS_ON);
break;
case L'3':
selection = SEL_BANK;
break;
case L'4':
case L' ':
selection = SEL_EXIT;
break;
default:
beep();
}
}
} else {
// Function or control key
switch (key) {
case KEY_ESC:
case KEY_CANCEL:
case KEY_EXIT:
case KEY_CTRL('C'):
case KEY_CTRL('G'):
case KEY_CTRL('\\'):
selection = SEL_EXIT;
break;
default:
beep();
}
}
}
curs_set(CURS_OFF);
deltxwin(); // "Enter selection" window
txrefresh();
if (selection == SEL_BANK) {
// Visit the Interstellar Trading Bank
visit_bank();
} else if (selection == SEL_EXIT) {
// Exit the Stock Exchange: nothing more to do
;
} else {
trade_shares(selection, &bid_used);
}
}
deltxwin(); // "Stock Exchange" window
txrefresh();
}
/************************************************************************
* Module-specific function prototypes *
************************************************************************/
// These functions are documented at the start of this file
/***********************************************************************/
// visit_bank: Visit the Interstellar Trading Bank
void visit_bank (void)
{
double credit_limit;
double val, max;
wint_t key;
bool done;
chtype *chbuf = xmalloc(BUFSIZE * sizeof(chtype));
int x, width;
credit_limit = (total_value(current_player) - player[current_player].debt)
* CREDIT_LIMIT_RATE;
if (credit_limit < 0.0) {
credit_limit = 0.0;
}
// Show the informational part of the Bank
newtxwin(10, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window);
center(curwin, 1, 0, attr_title, 0, 0, 1,
_(" Interstellar Trading Bank "));
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin) - 4, &width,
1, pgettext("label", "Current cash: "));
x = (getmaxx(curwin) + width - (BANK_VALUE_COLS + 2)) / 2;
rightch(curwin, 3, x, chbuf, 1, &width);
right(curwin, 3, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0,
1, " ^{%N^} ", player[current_player].cash);
right(curwin, 4, x, attr_normal, 0, 0, 1,
pgettext("label", "Current debt: "));
right(curwin, 4, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0,
1, " ^{%N^} ", player[current_player].debt);
right(curwin, 5, x, attr_normal, 0, 0, 1,
pgettext("label", "Interest rate: "));
right(curwin, 5, x + BANK_VALUE_COLS + 2, attr_normal, attr_highlight, 0,
1, " ^{%.2f%%^} ", interest_rate * 100.0);
right(curwin, 7, x, attr_highlight, 0, 0, 1,
/* TRANSLATORS: The "Total value", "Current cash", "Current
debt", "Interest rate" and "Credit limit" labels MUST all be
the same length (ie, right-padded with spaces as needed) and
must have at least one trailing space so that the display
routines work correctly. The maximum length of each label
is 36 characters.
Note that some of these labels are used for both the Player
Status window and the Trading Bank window. */
pgettext("label", "Credit limit: "));
whline(curwin, ' ' | attr_title, BANK_VALUE_COLS + 2);
right(curwin, 7, x + BANK_VALUE_COLS + 2, attr_title, 0, 0, 1,
" %N ", credit_limit);
wrefresh(curwin);
// Show menu of choices for the player
newtxwin(7, WIN_COLS - 4, 15, WCENTER, true, attr_normal_window);
center(curwin, 3, 0, attr_normal, attr_keycode, 0, 1,
/* TRANSLATORS: The "Borrow money", "Repay debt" and "Exit
from the Bank" menu options must all be the same length
(ie, padded with trailing spaces as required). The maximum
length is 72 characters. */
_("^{<1>^} Borrow money "));
center(curwin, 4, 0, attr_normal, attr_keycode, 0, 1,
_("^{<2>^} Repay debt "));
center(curwin, 5, 0, attr_normal, attr_keycode, 0, 1,
_("^{<3>^} Exit from the Bank"));
center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1,
_("Enter selection [^{1^}-^{3^}]: "));
curs_set(CURS_ON);
wrefresh(curwin);
done = false;
while (! done) {
if (gettxchar(curwin, &key) == OK) {
// Ordinary wide character
switch (key) {
case L'1':
case L'2':
case L'3':
left(curwin, getcury(curwin), getcurx(curwin), A_BOLD,
0, 0, 1, "%lc", key);
wrefresh(curwin);
done = true;
break;
case L' ':
done = true;
break;
default:
beep();
}
} else {
// Function or control key
switch (key) {
case KEY_ESC:
case KEY_CANCEL:
case KEY_EXIT:
case KEY_CTRL('C'):
case KEY_CTRL('G'):
case KEY_CTRL('\\'):
done = true;
break;
default:
beep();
}
}
}
curs_set(CURS_OFF);
switch (key) {
case L'1':
// Borrow money from the Bank
if (credit_limit == 0.0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" Insufficient Credit Limit "),
_("The Bank will not lend you any more money."));
} else {
chtype *chbuf_cursym;
int width_cursym;
int n, ret;
wbkgdset(curwin, attr_normal_window);
werase(curwin);
box(curwin, 0, 0);
n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0;
mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1,
getmaxx(curwin) / 2, &width_cursym, 1, "^{%ls^}",
currency_symbol);
chbuf_cursym = xchstrdup(chbuf);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin)
- BANK_INPUT_COLS - width_cursym - 6, &width, 1,
_("How much do you wish to borrow? "));
x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym
- n) / 2;
rightch(curwin, 3, x, chbuf, 1, &width);
// Show the currency symbol before or after the input field
if (lconvinfo.p_cs_precedes == 1) {
leftch(curwin, 3, x, chbuf_cursym, 1, &width_cursym);
x += width_cursym + n;
} else {
leftch(curwin, 3, x + BANK_INPUT_COLS + n, chbuf_cursym, 1,
&width_cursym);
}
ret = gettxdouble(curwin, &val, 0.0, credit_limit + ROUNDING_AMOUNT,
0.0, credit_limit, 3, x, BANK_INPUT_COLS,
attr_input_field);
if (ret == OK && val > ROUNDING_AMOUNT) {
player[current_player].cash += val;
player[current_player].debt += val * (interest_rate + 1.0);
}
free(chbuf_cursym);
}
break;
case L'2':
// Repay a debt
if (player[current_player].debt == 0.0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" No Debt "),
_("You have no debt to repay."));
} else if (player[current_player].cash == 0.0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" No Cash "),
_("You have no cash with which to repay the debt!"));
} else {
chtype *chbuf_cursym;
int width_cursym;
int n, ret;
wbkgdset(curwin, attr_normal_window);
werase(curwin);
box(curwin, 0, 0);
n = (lconvinfo.p_sep_by_space == 1) ? 1 : 0;
mkchstr(chbuf, BUFSIZE, attr_normal, attr_normal | A_BOLD, 0, 1,
getmaxx(curwin) / 2, &width_cursym, 1, "^{%ls^}",
currency_symbol);
chbuf_cursym = xchstrdup(chbuf);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, getmaxx(curwin)
- BANK_INPUT_COLS - width_cursym - 6, &width, 1,
_("How much do you wish to repay? "));
x = (getmaxx(curwin) + width - BANK_INPUT_COLS - width_cursym
- n) / 2;
rightch(curwin, 3, x, chbuf, 1, &width);
// Show the currency symbol before or after the input field
if (lconvinfo.p_cs_precedes == 1) {
leftch(curwin, 3, x, chbuf_cursym, 1, &width_cursym);
x += width_cursym + n;
} else {
leftch(curwin, 3, x + BANK_INPUT_COLS + n, chbuf_cursym, 1,
&width_cursym);
}
max = MIN(player[current_player].cash, player[current_player].debt);
ret = gettxdouble(curwin, &val, 0.0, max + ROUNDING_AMOUNT, 0.0,
max, 3, x, BANK_INPUT_COLS, attr_input_field);
if (ret == OK) {
player[current_player].cash -= val;
player[current_player].debt -= val;
if (player[current_player].cash < ROUNDING_AMOUNT) {
player[current_player].cash = 0.0;
}
if (player[current_player].debt < ROUNDING_AMOUNT) {
player[current_player].debt = 0.0;
}
}
free(chbuf_cursym);
}
break;
default:
break;
}
deltxwin(); // "Enter selection" window
deltxwin(); // Trading Bank window
txrefresh();
free(chbuf);
}
/***********************************************************************/
// trade_shares: Buy and sell shares in a particular company
void trade_shares (int num, bool *bid_used)
{
bool done;
int ret, w, x, mid;
long int maxshares, val;
double ownership;
chtype *chbuf;
int width;
wint_t key;
assert(num >= 0 && num < MAX_COMPANIES);
assert(company[num].on_map);
chbuf = xmalloc(BUFSIZE * sizeof(chtype));
ownership = (company[num].stock_issued == 0) ? 0.0 :
((double) player[current_player].stock_owned[num]
/ company[num].stock_issued);
// Show the informational part of the trade window
newtxwin(9, WIN_COLS - 4, 5, WCENTER, true, attr_normal_window);
w = getmaxx(curwin);
center(curwin, 1, 0, attr_title, 0, 0, 1,
/* TRANSLATORS: %ls represents the company name. */
_(" Stock Transaction in %ls "), company[num].name);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1,
/* TRANSLATORS: "Shares issued" represents the number of
shares already sold by the company to all players.
Note that the labels "Shares issued", "Shares left",
"Price per share" and "Return" must all be the same length
and must have at least one trailing space for the output
routines to work correctly. The maximum length of each
label is 22 characters. */
pgettext("label|Stock A", "Shares issued: "));
leftch(curwin, 3, 2, chbuf, 1, &width);
right(curwin, 3, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight,
0, 1, "^{%'ld^}", company[num].stock_issued);
left(curwin, 4, 2, attr_normal, 0, 0, 1,
/* TRANSLATORS: "Shares left" is the number of shares that are
left to be purchased in the current company. */
pgettext("label|Stock A", "Shares left: "));
right(curwin, 4, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight,
0, 1, "^{%'ld^}", company[num].max_stock - company[num].stock_issued);
left(curwin, 5, 2, attr_normal, 0, 0, 1,
/* TRANSLATORS: "Price per share" is the cost of each share in
the current company. */
pgettext("label|Stock A", "Price per share: "));
right(curwin, 5, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight,
0, 1, "^{%N^}", company[num].share_price);
left(curwin, 6, 2, attr_normal, 0, 0, 1,
/* TRANSLATORS: "Return" is the share return as a percentage. */
pgettext("label|Stock A", "Return: "));
right(curwin, 6, width + SHARE_PRICE_COLS + 2, attr_normal, attr_highlight,
0, 1, "^{%.2f%%^}", company[num].share_return * 100.0);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1, w / 2, &width, 1,
/* TRANSLATORS: "Current holdings" is the number of shares
the current player owns in this particular company.
Note that the labels "Current holdings", "Percentage owned"
and "Current cash" MUST all be the same length and contain at
least one trailing space for the display routines to work
correctly. The maximum length of each label is 18
characters. */
pgettext("label|Stock B", "Current holdings: "));
mid = MIN(w / 2, w - width - TRADE_VALUE_COLS - 4);
leftch(curwin, 3, mid, chbuf, 1, &width);
right(curwin, 3, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%'ld^} ",
player[current_player].stock_owned[num]);
left(curwin, 4, mid, attr_normal, 0, 0, 1,
/* TRANSLATORS: "Percentage owned" is the current player's
percentage ownership in this particular company. */
pgettext("label|Stock B", "Percentage owned: "));
right(curwin, 4, w - 2, attr_normal, attr_highlight, 0, 1, " ^{%.2f%%^} ",
ownership * 100.0);
left(curwin, 6, mid, attr_highlight, 0, 0, 1,
pgettext("label|Stock B", "Current cash: "));
whline(curwin, ' ' | attr_title, TRADE_VALUE_COLS + 2);
right(curwin, 6, w - 2, attr_title, 0, 0, 1, " %N ",
player[current_player].cash);
wrefresh(curwin);
// Show menu of choices for the player
newtxwin(7, WIN_COLS - 4, 14, WCENTER, true, attr_normal_window);
left(curwin, 3, 2, attr_normal, attr_keycode, 0, 1,
/* TRANSLATORS: Each label may be up to 35 characters wide
(for <1> and <2>) or 36 characters wide (for <3> and <4>). */
_("^{<1>^} Buy stock from company"));
left(curwin, 4, 2, attr_normal, attr_keycode, 0, 1,
_("^{<2>^} Sell stock back to company"));
left(curwin, 3, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1,
_("^{<3>^} Bid company to issue more shares"));
left(curwin, 4, getmaxx(curwin) / 2, attr_normal, attr_keycode, 0, 1,
_("^{<4>^} Exit to the Stock Exchange"));
center(curwin, 1, 0, attr_normal, attr_keycode, 0, 1,
_("Enter selection [^{1^}-^{4^}]: "));
curs_set(CURS_ON);
wrefresh(curwin);
done = false;
while (! done) {
if (gettxchar(curwin, &key) == OK) {
// Ordinary wide character
switch (key) {
case L'1':
case L'2':
case L'3':
case L'4':
left(curwin, getcury(curwin), getcurx(curwin), A_BOLD,
0, 0, 1, "%lc", key);
wrefresh(curwin);
done = true;
break;
case L' ':
done = true;
break;
default:
beep();
}
} else {
// Function or control key
switch (key) {
case KEY_ESC:
case KEY_CANCEL:
case KEY_EXIT:
case KEY_CTRL('C'):
case KEY_CTRL('G'):
case KEY_CTRL('\\'):
done = true;
break;
default:
beep();
}
}
}
curs_set(CURS_OFF);
switch (key) {
case L'1':
// Buy stock in company
maxshares = player[current_player].cash / company[num].share_price;
if (company[num].max_stock - company[num].stock_issued == 0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" No Shares Available "),
_("No more shares are available for purchase."));
} else if (maxshares <= 0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" Insufficient Cash "),
_("You do not have enough cash\n"
"to purchase additional shares."));
} else {
maxshares = MIN(maxshares, company[num].max_stock -
company[num].stock_issued);
wbkgdset(curwin, attr_normal_window);
werase(curwin);
box(curwin, 0, 0);
center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1,
ngettext("You can purchase ^{one^} share.",
"You can purchase up to ^{%'ld^} shares.",
maxshares), maxshares);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1,
getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1,
_("How many shares do you wish to purchase? "));
x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2;
rightch(curwin, 4, x, chbuf, 1, &width);
ret = gettxlong(curwin, &val, 0, maxshares, 0, maxshares, 4, x,
TRADE_INPUT_COLS, attr_input_field);
if (ret == OK) {
player[current_player].cash -= val * company[num].share_price;
player[current_player].stock_owned[num] += val;
company[num].stock_issued += val;
}
}
break;
case L'2':
// Sell stock back to company
maxshares = player[current_player].stock_owned[num];
if (maxshares == 0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" No Shares "),
_("You do not have any shares to sell."));
} else {
wbkgdset(curwin, attr_normal_window);
werase(curwin);
box(curwin, 0, 0);
center(curwin, 2, 0, attr_normal, attr_highlight, 0, 1,
ngettext("You can sell ^{one^} share.",
"You can sell up to ^{%'ld^} shares.",
maxshares), maxshares);
mkchstr(chbuf, BUFSIZE, attr_normal, 0, 0, 1,
getmaxx(curwin) - TRADE_INPUT_COLS - 4, &width, 1,
_("How many shares do you wish to sell? "));
x = (getmaxx(curwin) + width - TRADE_INPUT_COLS) / 2;
rightch(curwin, 4, x, chbuf, 1, &width);
ret = gettxlong(curwin, &val, 0, maxshares, 0, maxshares, 4, x,
TRADE_INPUT_COLS, attr_input_field);
if (ret == OK) {
company[num].stock_issued -= val;
player[current_player].stock_owned[num] -= val;
player[current_player].cash += val * company[num].share_price;
}
}
break;
case L'3':
// Bid company to issue more shares
maxshares = 0;
if (! *bid_used && randf() < ownership && randf() < BID_CHANCE) {
maxshares = randf() * ownership * MAX_SHARES_BIDDED;
company[num].max_stock += maxshares;
}
*bid_used = true;
if (maxshares == 0) {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_error_window,
attr_error_title, attr_error_highlight, 0, 0,
attr_error_waitforkey, _(" No Shares Issued "),
/* TRANSLATORS: %ls represents the company name. */
_("%ls has refused\nto issue more shares."),
company[num].name);
} else {
txdlgbox(MAX_DLG_LINES, 50, 8, WCENTER, attr_normal_window,
attr_title, attr_normal, attr_highlight, 0,
attr_waitforkey, _(" Shares Issued "),
/* TRANSLATORS: %ls represents the company name. */
ngettext("%ls has issued\n^{one^} more share.",
"%ls has issued\n^{%'ld^} more shares.",
maxshares), company[num].name, maxshares);
}
break;
default:
break;
}
deltxwin(); // "Enter selection" window
deltxwin(); // Stock Transaction window
txrefresh();
free(chbuf);
}
/***********************************************************************/
// End of file