void trdswitchown(int type, void *ptr, int newown) { struct trdstr trade; union empobj_storage tg; int n; for (n = 0; gettrade(n, &trade); n++) { if (trade.trd_unitid < 0) continue; if (!trade_getitem(&trade, &tg)) continue; if (trade.trd_type != type) continue; if (tg.gen.uid != ((struct empobj *)ptr)->uid) continue; if (trade.trd_owner == trade.trd_maxbidder) trade.trd_maxbidder = newown; trade.trd_owner = newown; if (newown == 0) trade.trd_unitid = -1; puttrade(n, &trade); return; } }
int ontradingblock(int type, void *ptr) { struct trdstr trade; union empobj_storage tg; int n; for (n = 0; gettrade(n, &trade); n++) { if (trade.trd_unitid < 0) continue; if (!trade_getitem(&trade, &tg)) continue; if (trade.trd_type != type) continue; if (tg.gen.uid == ((struct empobj *)ptr)->uid) return 1; } return 0; }
/* * format: trade */ int trad(void) { struct sctstr sect; struct natstr *natp; struct comstr comt; int lotno; float price; coord sx, sy; int n; char *p; struct nstr_item ni; struct trdstr trade; struct trdstr tmpt; union empobj_storage tg; double canspend; time_t now, tleft; int bid; double tally; int i; char buf[1024]; if (!opt_MARKET) { pr("The market is disabled.\n"); return RET_FAIL; } /* First, we execute all trades, so that we can only buy what is available. */ check_market(); check_trade(); pr("\n Empire Trade Report\n "); prdate(); n = 0; pr(" lot high bid by time left owner description\n"); pr(" --- -------- -- --------- ----- -------------------------\n"); snxtitem_all(&ni, EF_TRADE); while (nxtitem(&ni, &trade)) { if (trade.trd_owner == 0) continue; if (!trade_getitem(&trade, &tg)) { continue; }; pr(" %3d ", ni.cur); (void)time(&now); tleft = trade.trd_markettime + TRADE_DELAY - now; if (tleft < 0) tleft = 0; pr("$%7d %2d %5.2f hrs ", trade.trd_price, trade.trd_maxbidder, tleft / 3600.0); trade_desc(&tg.gen); /* XXX */ pr("\n"); if (trade.trd_owner == player->cnum && !player->god) pr(" (your own lot)\n"); n++; } if (n == 0) { pr("Nothing to buy at the moment...\n"); return RET_OK; } p = getstring("Which lot to buy: ", buf); if (!p || !*p) return RET_OK; if (isdigit(*p) == 0) return RET_OK; lotno = atoi(p); if (lotno < 0 || lotno >= ni.cur) { pr("Bad lot number\n"); return RET_OK; } if (!gettrade(lotno, &trade)) { pr("No such lot number\n"); return RET_OK; } if (trade.trd_unitid < 0) { pr("Invalid lot number.\n"); return RET_OK; } if (!trade_getitem(&trade, &tg)) { pr("Can't find trade #%d!\n", trade.trd_unitid); trade.trd_owner = 0; trade.trd_unitid = -1; if (!puttrade(lotno, &trade)) { logerror("trad: can't write trade"); pr("Couldn't save after getitem failed; get help!\n"); return RET_FAIL; } return RET_OK; } switch (trade.trd_type) { case EF_NUKE: case EF_PLANE: case EF_SHIP: case EF_LAND: break; default: pr("Bad unit type on lot number %d\n", lotno); return RET_FAIL; } if (trade.trd_owner == player->cnum) { pr("You can't buy from yourself!\n"); return RET_OK; } price = trade.trd_price; natp = getnatp(player->cnum); if (natp->nat_money < price) { pr("You don't have %.2f to spend!\n", price); return RET_OK; } tally = 0.0; for (i = 0; gettrade(i, &tmpt); i++) { if (tmpt.trd_maxbidder == player->cnum && tmpt.trd_unitid >= 0 && tmpt.trd_owner != player->cnum) { tally += tmpt.trd_price * tradetax; } } for (i = 0; getcomm(i, &comt); i++) { if (comt.com_maxbidder == player->cnum && comt.com_owner != 0 && comt.com_owner != player->cnum) { tally += (comt.com_price * comt.com_amount) * buytax; } } canspend = natp->nat_money - tally; /* Find the destination sector for the trade */ if (((trade.trd_type == EF_PLANE) && !pln_is_in_orbit(&tg.plane)) || (trade.trd_type == EF_NUKE)) { while (1) { p = getstring("Destination sector: ", buf); if (!trade_check_ok(&trade, &tg.gen)) return RET_FAIL; if (!p) { return RET_FAIL; } if (!sarg_xy(p, &sx, &sy) || !getsect(sx, sy, §)) { pr("Bad sector designation; try again!\n"); continue; } if (!player->owner) { pr("You don't own that sector; try again!\n"); continue; } if (!(plchr[tg.plane.pln_type].pl_flags & P_V)) { if (!player->god && (sect.sct_type != SCT_AIRPT)) { pr("Destination sector is not an airfield!\n"); continue; } if (!player->god && (sect.sct_effic < 60)) { pr("That airport still under construction!\n"); continue; } } break; } } else if (trade.trd_type == EF_LAND) { while (1) { p = getstring("Destination sector: ", buf); if (!trade_check_ok(&trade, &tg.gen)) return RET_FAIL; if (!p) { return RET_FAIL; } if (!sarg_xy(p, &sx, &sy) || !getsect(sx, sy, §)) { pr("Bad sector designation; try again!\n"); continue; } if (!player->owner) { pr("You don't own that sector; try again!\n"); continue; } if (!player->god && (sect.sct_type != SCT_HEADQ)) { pr("Destination sector is not a headquarters!\n"); continue; } if (!player->god && (sect.sct_effic < 60)) { pr("That headquarters still under construction!\n"); continue; } break; } } else { /* This trade doesn't teleport; make destination invalid */ sx = 1; sy = 0; } p = getstring("How much do you bid: ", buf); if (!p || !*p) return RET_OK; if (!trade_check_ok(&trade, &tg.gen)) return RET_FAIL; bid = atoi(p); if (bid < price) bid = price; if (bid > canspend) { pr("You don't have %.2f to spend!\n", price); return RET_OK; } if (bid > trade.trd_price) { time(&now); if (trade.trd_markettime + TRADE_DELAY - now < minutes(5) && trade.trd_maxbidder != player->cnum) trade.trd_markettime = now + minutes(5) - TRADE_DELAY; trade.trd_price = bid; trade.trd_maxbidder = player->cnum; trade.trd_x = sx; trade.trd_y = sy; pr("Your bid on lot #%d is being considered.\n", lotno); if (!puttrade(lotno, &trade)) pr("Problems with the trade file. Get help\n"); } else pr("Your bid wasn't high enough (you need to bid more than someone else.)\n"); check_trade(); return RET_OK; }
int check_trade(void) { int n; struct natstr *natp; struct trdstr trade; union empobj_storage tg; time_t now; int price; int saveid; natid seller; for (n = 0; gettrade(n, &trade); n++) { if (trade.trd_unitid < 0) continue; if (!trade_getitem(&trade, &tg)) continue; if (tg.gen.own == 0) { trade.trd_owner = 0; trade.trd_unitid = -1; puttrade(n, &trade); continue; } if (tg.gen.own != trade.trd_owner) { logerror("Something weird, tg.gen.own != trade.trd_owner!\n"); trade.trd_owner = 0; trade.trd_unitid = -1; puttrade(n, &trade); continue; } if (trade.trd_owner == trade.trd_maxbidder) continue; (void)time(&now); if (trade.trd_markettime + TRADE_DELAY > now) continue; saveid = trade.trd_unitid; seller = trade.trd_owner; trade.trd_owner = 0; trade.trd_unitid = -1; if (!puttrade(n, &trade)) { logerror("Couldn't save trade after purchase; get help!\n"); continue; } price = trade.trd_price; natp = getnatp(trade.trd_maxbidder); if (natp->nat_money < price) { nreport(trade.trd_maxbidder, N_WELCH_DEAL, seller, 1); wu(0, seller, "%s tried to buy a %s #%d from you for $%.2f\n", cname(trade.trd_maxbidder), trade_nameof(&trade, &tg.gen), saveid, price * tradetax); wu(0, seller, " but couldn't afford it.\n"); wu(0, seller, " Your item was taken off the market.\n"); wu(0, trade.trd_maxbidder, "You tried to buy %s #%d from %s for $%d\n", trade_nameof(&trade, &tg.gen), saveid, cname(seller), price); wu(0, trade.trd_maxbidder, "but couldn't afford it.\n"); continue; } /* If we get this far, the sale will go through. */ natp->nat_money -= price; putnat(natp); natp = getnatp(seller); natp->nat_money += roundavg(price * tradetax); putnat(natp); switch (trade.trd_type) { case EF_NUKE: tg.nuke.nuk_x = trade.trd_x; tg.nuke.nuk_y = trade.trd_y; tg.nuke.nuk_plane = -1; break; case EF_PLANE: if (!pln_is_in_orbit(&tg.plane)) { tg.plane.pln_x = trade.trd_x; tg.plane.pln_y = trade.trd_y; } if (opt_MOB_ACCESS) { tg.plane.pln_mobil = -(etu_per_update / sect_mob_neg_factor); game_tick_to_now(&tg.plane.pln_access); } else { tg.plane.pln_mobil = 0; } tg.plane.pln_harden = 0; tg.plane.pln_ship = -1; tg.plane.pln_land = -1; break; case EF_SHIP: break; case EF_LAND: tg.land.lnd_x = trade.trd_x; tg.land.lnd_y = trade.trd_y; if (opt_MOB_ACCESS) { tg.land.lnd_mobil = -(etu_per_update / sect_mob_neg_factor); game_tick_to_now(&tg.land.lnd_access); } else { tg.land.lnd_mobil = 0; } tg.land.lnd_harden = 0; unit_drop_cargo(&tg.gen, 0); tg.land.lnd_ship = -1; tg.land.lnd_land = -1; break; default: logerror("Bad trade type %d in trade\n", trade.trd_type); break; } unit_give_away(&tg.gen, trade.trd_maxbidder, 0); put_empobj(trade.trd_type, saveid, &tg.gen); nreport(seller, N_MAKE_SALE, trade.trd_maxbidder, 1); wu(0, seller, "%s bought %s #%d from you for $%.2f\n", cname(trade.trd_maxbidder), trade_nameof(&trade, &tg.gen), saveid, price * tradetax); wu(0, trade.trd_maxbidder, "The bidding is over & you bought %s #%d from %s for $%d\n", trade_nameof(&trade, &tg.gen), saveid, cname(seller), price); } return RET_OK; }
/* * format: buy <COMMODITY> * */ int buy(void) { struct sctstr sect; struct natstr *natp; struct comstr comm; struct comstr comt; struct trdstr tmpt; struct ichrstr *ip; 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); 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) return RET_SYN; if (*p == 0) return RET_SYN; o = atoi(p); if (o < 0) return RET_SYN; if (!getcomm(o, &comm) || comm.com_owner == 0) { pr("Invalid lot number.\n"); return RET_OK; } 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) { pr("You can't bid on your own lot.\n"); return RET_OK; } 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) { 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); return RET_FAIL; } /* check to see if all of the bids that this player has out plus this new bid would make him go broke. Ken, I ought to skin you alive for making me code this part up.*/ tally = 0.0; for (n = 0; gettrade(n, &tmpt); n++) { if (tmpt.trd_maxbidder == player->cnum && tmpt.trd_unitid >= 0 && tmpt.trd_owner != player->cnum) { tally += tmpt.trd_price * tradetax; } } 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_price * comt.com_amount * buytax; } } canspend = natp->nat_money - tally; check_comm_ok(&comm); 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; } if (!(p = getstarg(player->argp[4], "destination sector : ", buf))) return RET_SYN; if (!sarg_xy(p, &x, &y)) return RET_SYN; if (!getsect(x, y, §)) { pr("Could not access sector"); 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"); return RET_FAIL; } if (sect.sct_effic < 60) { pr("That sector is under construction.\n"); return RET_FAIL; } n = sect.sct_item[ip->i_uid]; qty = comm.com_amount; 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; } if (bid * comm.com_amount > natp->nat_money) { pr("You don't have that much to spend!\n"); return RET_FAIL; } if (!check_comm_ok(&comm)) return RET_FAIL; if (bid > 0.04 + comm.com_price) { comm.com_price = bid; time(&now); 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; putcomm(o, &comm); pr("Your bid is being considered.\n"); } else { pr("Your bid wasn't high enough (you need to bid at least $0.05 higher\n"); pr("than the last bid.\n"); return RET_OK; } check_market(); return RET_OK; }