X-Git-Url: http://git.pond.sub.org/?p=empserver;a=blobdiff_plain;f=src%2Flib%2Fcommands%2Fbuy.c;h=72afa28c20e10c86349a77d15dfadd1a31864f9d;hp=c891dec7dfdba8bc621a20299c897a53bd8a7283;hb=a021a20e551f1f0ab05ad6da336dc28c83a10075;hpb=d8b7fdfae1c42f6ab23e74a011d3ed12c4c78f16 diff --git a/src/lib/commands/buy.c b/src/lib/commands/buy.c index c891dec7d..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,47 +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 "deity.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" - -extern int MARK_DELAY; +#include "trade.h" /* * format: buy @@ -66,60 +53,57 @@ 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; - coord x, y; - char *p; - float bid; - time_t now; - double tally; - double canspend; - extern double buytax; - extern double tradetax; - s_char buf[1024]; - + int qty; + int o, n; + coord x, y; + char *p; + float bid; + time_t now; + double tally; + double canspend; + 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) - return RET_SYN; + if (!p) + return RET_SYN; if (*p == 0) - return RET_SYN; + return RET_SYN; o = atoi(p); if (o < 0) return RET_SYN; - if(!getcomm(o, &comm) || comm.com_owner == 0){ + if (!getcomm(o, &comm) || comm.com_owner == 0) { 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; } - if (comm.com_owner == player->cnum){ + if (comm.com_owner == player->cnum) { 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) - return RET_SYN; + 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); @@ -129,23 +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; + 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; + comt.com_owner != 0 && comt.com_owner != player->cnum) { + 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; @@ -158,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"); @@ -167,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)); + if (bid * comm.com_amount > natp->nat_money) { + pr("You don't have that much to spend!\n"); 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) { - 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; @@ -217,7 +179,7 @@ buy(void) pr("than the last bid.\n"); return RET_OK; } - + check_market(); return RET_OK; @@ -226,149 +188,70 @@ buy(void) int check_market(void) { - extern double buytax; 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) + 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"); - wu(0, comm.com_owner, + "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; - } else if (sect->sct_type != SCT_WAREH && sect->sct_type != SCT_HARBR) { - wu(0, comm.com_maxbidder, + } else if (sect->sct_type != SCT_WAREH + && sect->sct_type != SCT_HARBR) { + wu(0, comm.com_maxbidder, "Sector not a warehouse now, sale #%d fell though.\n", n); - wu(0, comm.com_owner, + 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) { - wu(0, comm.com_maxbidder, + } 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, + 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", - cname(comm.com_maxbidder), comm.com_amount, - comm.com_type, 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); - 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; + wu(0, comm.com_owner, "%s bought %d %s from you for $%.2f\n", + cname(comm.com_maxbidder), comm.com_amount, + ichr[comm.com_type].i_name, gain); + wu(0, comm.com_maxbidder, + "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); + 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; } - -