diff --git a/src/Corporation/Actions.ts b/src/Corporation/Actions.ts index 47373d373..8bc79b946 100644 --- a/src/Corporation/Actions.ts +++ b/src/Corporation/Actions.ts @@ -332,8 +332,10 @@ export function buyMaterial(division: Division, material: Material, amt: number) if (!isRelevantMaterial(material.name, division)) { throw new Error(`${material.name} is not a relevant material for industry ${division.type}`); } - if (isNaN(amt) || amt < 0) { - throw new Error(`Invalid amount '${amt}' to buy material '${material.name}'`); + if (!Number.isFinite(amt) || amt < 0) { + throw new Error( + `Invalid amount '${amt}' to buy material '${material.name}'. Must be numeric and greater than or equal to 0`, + ); } material.buyAmount = amt; } @@ -350,22 +352,27 @@ export function bulkPurchase( } const matSize = MaterialInfo[material.name].size; const maxAmount = (warehouse.size - warehouse.sizeUsed) / matSize; - if (isNaN(amt) || amt < 0) { - throw new Error(`Invalid input amount`); + if (!Number.isFinite(amt) || amt < 0) { + throw new Error( + `Invalid amount '${amt}' to buy material '${material.name}'. Must be numeric and greater than or equal to 0`, + ); } if (amt > maxAmount) { throw new Error(`You do not have enough warehouse size to fit this purchase`); } + // Special case: if "amount" is 0, this is a no-op. + if (amt === 0) { + return; + } const cost = amt * material.marketPrice; - if (corp.funds >= cost) { - corp.loseFunds(cost, "materials"); - material.averagePrice = - (material.averagePrice * material.stored + material.marketPrice * amt) / (material.stored + amt); - material.stored += amt; - warehouse.sizeUsed = warehouse.sizeUsed + amt * matSize; - } else { + if (corp.funds < cost) { throw new Error(`You cannot afford this purchase.`); } + corp.loseFunds(cost, "materials"); + material.averagePrice = + (material.averagePrice * material.stored + material.marketPrice * amt) / (material.stored + amt); + material.stored += amt; + warehouse.sizeUsed = warehouse.sizeUsed + amt * matSize; } export function sellShares(corporation: Corporation, numShares: number): number { diff --git a/src/Corporation/Division.ts b/src/Corporation/Division.ts index 767413db8..1384c246c 100644 --- a/src/Corporation/Division.ts +++ b/src/Corporation/Division.ts @@ -375,7 +375,7 @@ export class Division { // buy them for (const [matName, [buyAmt]] of getRecordEntries(smartBuy)) { const mat = warehouse.materials[matName]; - if (mat.stored + buyAmt != 0) { + if (mat.stored + buyAmt !== 0) { mat.quality = (mat.quality * mat.stored + 1 * buyAmt) / (mat.stored + buyAmt); mat.averagePrice = (mat.averagePrice * mat.stored + mat.marketPrice * buyAmt) / (mat.stored + buyAmt); } else { diff --git a/src/Corporation/Material.ts b/src/Corporation/Material.ts index 463615fd7..bc2390ea2 100644 --- a/src/Corporation/Material.ts +++ b/src/Corporation/Material.ts @@ -139,8 +139,11 @@ export class Material { if (isNaN(material.quality)) { material.quality = 1; } - // averagePrice has not been initialized properly, so if it is 0 (wrong initial value), we set it to marketPrice. - if (material.averagePrice === 0) { + /** + * averagePrice has not been calculated properly, so if it is an invalid value (Number.isFinite returns false) or 0 + * (wrong initial value), we set it to marketPrice. + */ + if (!Number.isFinite(material.averagePrice) || material.averagePrice === 0) { material.averagePrice = material.marketPrice; } return material; diff --git a/src/NetscriptFunctions/Corporation.ts b/src/NetscriptFunctions/Corporation.ts index 64555a234..2cd5b2426 100644 --- a/src/NetscriptFunctions/Corporation.ts +++ b/src/NetscriptFunctions/Corporation.ts @@ -336,8 +336,6 @@ export function NetscriptCorporation(): InternalAPI { const cityName = getEnumHelper("CityName").nsGetMember(ctx, _cityName); const materialName = getEnumHelper("CorpMaterialName").nsGetMember(ctx, _materialName, "materialName"); const amt = helpers.number(ctx, "amt", _amt); - if (amt < 0 || !Number.isFinite(amt)) - throw new Error("Invalid value for amount field! Must be numeric and greater than or equal to 0"); const material = getMaterial(divisionName, cityName, materialName); buyMaterial(division, material, amt); },