X-Git-Url: http://git.pond.sub.org/?p=empserver;a=blobdiff_plain;f=src%2Flib%2Fcommands%2Fbuy.c;h=72afa28c20e10c86349a77d15dfadd1a31864f9d;hp=ab92e0eb72605076dd2e83fb5b8a186aa6eab260;hb=a021a20e551f1f0ab05ad6da336dc28c83a10075;hpb=46da1aec7a91889e4aa137fe0f22eb2cf587b359 diff --git a/src/lib/commands/buy.c b/src/lib/commands/buy.c index ab92e0eb7..72afa28c2 100644 --- a/src/lib/commands/buy.c +++ b/src/lib/commands/buy.c @@ -1,11 +1,11 @@ /* * Empire - A multi-player, client/server Internet based war game. - * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak, - * Ken Stevens, Steve McClure + * Copyright (C) 1986-2021, Dave Pare, Jeff Bailey, Thomas Ruschak, + * Ken Stevens, Steve McClure, Markus Armbruster * - * This program is free software; you can redistribute it and/or modify + * Empire 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 2 of the License, or + * 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, @@ -14,44 +14,34 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * along with this program. If not, see . * * --- * - * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the - * related information and legal notices. It is expected that any future - * projects/authors will amend these files as needed. + * See files README, COPYING and CREDITS in the root of the source + * tree for related information and legal notices. It is expected + * that future projects/authors will amend these files as needed. * * --- * * buy.c: Buy commodities from other nations - * + * * Known contributors to this file: * Dave Pare, 1986 * Pat Loney, 1992 * Steve McClure, 1996-2000 + * Markus Armbruster, 2004-2021 */ -#include "misc.h" -#include "xy.h" -#include "file.h" -#include "var.h" -#include "sect.h" -#include "nat.h" -#include "news.h" -#include "nsc.h" -#include "item.h" -#include "land.h" -#include "commodity.h" -#include "plane.h" -#include "nuke.h" -#include "ship.h" -#include "trade.h" -#include "player.h" -#include "loan.h" +#include + +#include "chance.h" #include "commands.h" +#include "commodity.h" +#include "item.h" +#include "news.h" #include "optlist.h" +#include "trade.h" /* * format: buy @@ -63,29 +53,31 @@ buy(void) struct sctstr sect; struct natstr *natp; struct comstr comm; - struct comstr ncomm; struct comstr comt; struct trdstr tmpt; struct ichrstr *ip; int qty; - int o, n, q; + int o, n; coord x, y; char *p; float bid; time_t now; double tally; double canspend; - s_char buf[1024]; + char buf[1024]; if (!opt_MARKET) { pr("The market is disabled.\n"); return RET_FAIL; } natp = getnatp(player->cnum); - display_mark(player->argp[1]); + ip = whatitem(player->argp[1], "Commodity you want to buy: "); + if (!ip) + return RET_SYN; + display_mark(ip->i_uid, 0); pr("\n"); p = getstarg(player->argp[2], "Which lot are you bidding on: ", buf); - if (p == 0) + if (!p) return RET_SYN; if (*p == 0) return RET_SYN; @@ -96,8 +88,7 @@ buy(void) pr("Invalid lot number.\n"); return RET_OK; } - if (player->argp[1] && *(player->argp[1]) && - comm.com_type != player->argp[1][0]) { + if (comm.com_type != ip->i_uid) { pr("That lot is not of the type you specified.\n"); return RET_OK; } @@ -105,16 +96,14 @@ buy(void) pr("You can't bid on your own lot.\n"); return RET_OK; } - pr("WARNING! This market issues credit. If you make more\n"); - pr(" bids than your treasury can cover at the time of sale,\n"); - pr(" you can potentially go into financial ruin, and see no\n"); - pr(" gains. You have been warned.\n\n"); - if ((p = getstarg(player->argp[3], "How much per unit: ", buf)) == 0) + if (!(p = getstarg(player->argp[3], "How much per unit: ", buf))) return RET_SYN; bid = atof(p); if (bid <= 0) return RET_FAIL; - if (natp->nat_money < (bid * comm.com_amount * buytax)) { + if (!check_comm_ok(&comm)) + return RET_FAIL; + if (natp->nat_money < bid * comm.com_amount * buytax) { pr("This purchase would cost %.2f, %.2f more than you have.\n", bid * comm.com_amount * buytax, bid * comm.com_amount * buytax - natp->nat_money); @@ -124,21 +113,22 @@ buy(void) would make him go broke. Ken, I ought to skin you alive for making me code this part up.*/ tally = 0.0; - for (q = 0; gettrade(q, &tmpt); q++) { + for (n = 0; gettrade(n, &tmpt); n++) { + if (!tmpt.trd_owner) + continue; if (tmpt.trd_maxbidder == player->cnum && - tmpt.trd_unitid >= 0 && tmpt.trd_owner != player->cnum) { - tally += tmpt.trd_maxprice * tradetax; + tmpt.trd_owner != player->cnum) { + tally += tmpt.trd_price * tradetax; } } - for (q = 0; getcomm(q, &comt); q++) { + for (n = 0; getcomm(n, &comt); n++) { if (comt.com_maxbidder == player->cnum && comt.com_owner != 0 && comt.com_owner != player->cnum) { - tally += (comt.com_maxprice * comt.com_amount) * buytax; + tally += comt.com_price * comt.com_amount * buytax; } } canspend = natp->nat_money - tally; - getcomm(o, &comm); - if ((bid * comm.com_amount * buytax) > canspend) { + if (bid * comm.com_amount * buytax > canspend) { pr("You have overextended yourself in the market\n"); pr("You can not bid on the current items at that price.\n"); return RET_OK; @@ -151,6 +141,8 @@ buy(void) pr("Could not access sector"); return RET_FAIL; } + if (!check_comm_ok(&comm)) + return RET_FAIL; if ((sect.sct_type != SCT_WAREH && sect.sct_type != SCT_HARBR) || sect.sct_own != player->cnum) { pr("The destination sector is not one of your warehouses.\n"); @@ -160,46 +152,23 @@ buy(void) pr("That sector is under construction.\n"); return RET_FAIL; } - ip = whichitem(comm.com_type); - n = getvar(ip->i_vtype, (char *)§, EF_SECTOR); + n = sect.sct_item[ip->i_uid]; qty = comm.com_amount; - if (qty + n > 9990) { + if (qty + n > ITEM_MAX) { pr("That sector cannot hold %d more %s. It currently holds %d.\n", qty, ip->i_name, n); return RET_FAIL; } - /* First we check for room, then we yank back. Probably not necessary. */ - if (putvar(ip->i_vtype, n + qty, (char *)§, EF_SECTOR) <= 0) { - pr("No room to store %s in %s\n", - ip->i_name, xyas(sect.sct_x, sect.sct_y, player->cnum)); - return RET_FAIL; - } - if (putvar(ip->i_vtype, n, (char *)§, EF_SECTOR) <= 0) { - pr("Something weird just happened, tell the deity.\n"); - logerror("buy.c: putvar failed.\n"); - return RET_FAIL; - } - if ((bid * comm.com_amount) > natp->nat_money) { + if (bid * comm.com_amount > natp->nat_money) { pr("You don't have that much to spend!\n"); return RET_FAIL; } - getcomm(o, &ncomm); - if (!ncomm.com_owner) { - pr("That lot has been taken off the market.\n"); - return RET_FAIL; - } - if (bid > 0.04 + comm.com_maxprice) { - comm.com_maxprice = bid; - /* Add five minutes to the time if less than 5 minutes */ + if (bid > 0.04 + comm.com_price) { + comm.com_price = bid; time(&now); - if (((MARK_DELAY - (now - comm.com_markettime)) < 300) && - comm.com_maxbidder != player->cnum) { - comm.com_markettime += 300; - /* Special case - what if so much time has gone by? Well, - Just reset the markettime so that only 5 minutes are left */ - if ((MARK_DELAY - (now - comm.com_markettime)) < 0) - comm.com_markettime = (now - (MARK_DELAY - 300)); - } + if (comm.com_markettime + MARK_DELAY - now < minutes(5) && + comm.com_maxbidder != player->cnum) + comm.com_markettime = now + minutes(5) - MARK_DELAY; comm.com_maxbidder = player->cnum; comm.com_x = x; comm.com_y = y; @@ -221,119 +190,32 @@ check_market(void) { struct comstr comm; struct sctstr *sect; - struct ichrstr *ip; struct natstr *natp; int m; int n; time_t now; - double tmoney; - double tleft; - double subleft; - double monleft; double gain; double price; - struct lonstr loan; - long outstanding; /* Outstanding debt */ - long couval; /* Value of country's goods */ - int foundloan; - int j; -/* logerror("Checking the market.\n");*/ for (n = 0; getcomm(n, &comm); n++) { if (comm.com_maxbidder == comm.com_owner || comm.com_owner == 0) continue; (void)time(&now); - tleft = MARK_DELAY / 3600.0 - (now - comm.com_markettime) / 3600.0; - if (tleft < 0) - tleft = 0; - if (tleft > 0.0) + if (comm.com_markettime + MARK_DELAY > now) + continue; + if (CANT_HAPPEN(comm.com_type <= I_NONE || comm.com_type > I_MAX)) continue; - ip = whichitem(comm.com_type); sect = getsectp(comm.com_x, comm.com_y); - m = getvar(ip->i_vtype, (char *)sect, EF_SECTOR); - - monleft = 0; + m = sect->sct_item[comm.com_type]; - price = comm.com_maxprice * comm.com_amount * buytax; - gain = comm.com_maxprice * comm.com_amount; + price = comm.com_price * comm.com_amount * buytax; + gain = comm.com_price * comm.com_amount; natp = getnatp(comm.com_maxbidder); - tmoney = natp->nat_money; - if (tmoney <= 0) - monleft = price; - if (tmoney < price && tmoney > 0) { - monleft = price - (tmoney - 1); - tmoney = 1; - price = price - monleft; - } else if (tmoney > 0) { - monleft = 0; - tmoney = tmoney - price; - } - - /* Subtract the amount of money that needs to come out in a loan. */ - subleft = monleft; - - if (opt_LOANS) { - /* Try to make a loan for the rest from the owner. */ - if (monleft > 0 && tmoney > 0) { - if ((float)((float)price / (float)(price + monleft)) < 0.1) { - wu(0, comm.com_maxbidder, - "You need at least 10 percent down to purchase something on credit.\n"); - } else { - couval = get_couval(comm.com_maxbidder); - outstanding = get_outstand(comm.com_maxbidder); - couval = couval - outstanding; - if (couval > monleft) { - /* Make the loan */ - foundloan = 0; - for (j = 0; getloan(j, &loan); j++) { - if (loan.l_status != LS_FREE) - continue; - foundloan = 1; - break; - } - if (!foundloan) - ef_extend(EF_LOAN, 1); - loan.l_status = LS_SIGNED; - loan.l_loner = comm.com_owner; - loan.l_lonee = comm.com_maxbidder; - loan.l_irate = 25; - loan.l_ldur = 4; - loan.l_amtpaid = 0; - loan.l_amtdue = monleft; - time(&loan.l_lastpay); - loan.l_duedate = - (loan.l_ldur * SECS_PER_DAY) + loan.l_lastpay; - loan.l_uid = j; - if (!putloan(j, &loan)) - logerror("Error writing to the loan file.\n"); - else - monleft = 0; - nreport(comm.com_maxbidder, N_FIN_TROUBLE, - comm.com_owner, 1); - wu(0, comm.com_maxbidder, - "You just took loan #%d for $%.2f to cover the cost of your purchase.\n", - j, loan.l_amtdue); - wu(0, comm.com_owner, - "You just extended loan #%d to %s to help with the purchase cose.\n", - j, cname(comm.com_maxbidder)); - } else { - nreport(comm.com_maxbidder, N_CREDIT_JUNK, - comm.com_owner, 1); - wu(0, comm.com_maxbidder, - "You don't have enough credit to get a loan.\n"); - wu(0, comm.com_owner, - "You just turned down a loan to %s.\n", - cname(comm.com_maxbidder)); - } - } - } - } - - if (monleft > 0) { + if (natp->nat_money < price) { nreport(comm.com_maxbidder, N_WELCH_DEAL, comm.com_owner, 1); wu(0, comm.com_maxbidder, - "You didn't have enough cash/credit to cover the cost.\n"); + "You didn't have enough cash to cover the cost.\n"); wu(0, comm.com_owner, "Sale #%d fell through. Goods remain on the market.\n", n); comm.com_maxbidder = comm.com_owner; @@ -344,33 +226,32 @@ check_market(void) wu(0, comm.com_owner, "Sale #%d fell through. Goods remain on the market.\n", n); comm.com_maxbidder = comm.com_owner; - } else if (putvar(ip->i_vtype, m + comm.com_amount, - (char *)sect, EF_SECTOR) <= 0) { + } else if (m + comm.com_amount > ITEM_MAX) { wu(0, comm.com_maxbidder, "Warehouse full, sale #%d fell though.\n", n); wu(0, comm.com_owner, "Sale #%d fell through. Goods remain on the market.\n", n); comm.com_maxbidder = comm.com_owner; } else { + sect->sct_item[comm.com_type] = m + comm.com_amount; putsect(sect); nreport(comm.com_owner, N_MAKE_SALE, comm.com_maxbidder, 1); - wu(0, comm.com_owner, "%s bought %d %c's from you for $%.2f\n", + wu(0, comm.com_owner, "%s bought %d %s from you for $%.2f\n", cname(comm.com_maxbidder), comm.com_amount, - comm.com_type, gain); + ichr[comm.com_type].i_name, gain); wu(0, comm.com_maxbidder, - "You just bought %d %c's from %s for $%.2f\n", - comm.com_amount, comm.com_type, cname(comm.com_owner), - gain * buytax); + "You just bought %d %s from %s for $%.2f\n", + comm.com_amount, ichr[comm.com_type].i_name, + cname(comm.com_owner), price); + natp->nat_money -= roundavg(price); + putnat(natp); natp = getnatp(comm.com_owner); - /* Make sure we subtract the amount that came out in a loan */ - natp->nat_money += (gain - subleft); - natp = getnatp(comm.com_maxbidder); - natp->nat_money = tmoney; + natp->nat_money += roundavg(gain); + putnat(natp); comm.com_owner = 0; } comm.com_owner = 0; putcomm(n, &comm); } -/* logerror("Done checking the market.\n");*/ return RET_OK; }