diff --git a/devNotes/Economy notes.txt b/devNotes/Economy notes.txt new file mode 100644 index 0000000000000000000000000000000000000000..b6be489ac0886cefd81e9d5f10cfdb35600eed18 --- /dev/null +++ b/devNotes/Economy notes.txt @@ -0,0 +1,47 @@ +This document gives an overview of some of the economic mechanics, especially the ones spread across multiple files and functions. + +Determining the prices for whoring; + +The general principle behind the pricing is one of supply and demand. +Getting our hands on the appropriate information takes some doing due to how the game operates. +Supply and demand needs to be determined before the slave reports are generated, as such it takes place at the top of 'slaveAssignmentsReport.tw'. +Finding the demand is relatively straightforward, as it depends on the current arcology population of the various classes as well as visitors. +Finding the supply requires more work as all slaves tasked with sexually serving the populace need to be considered. +The function 'slaveJobValues()' takes care of pretty much all of that and can be found in 'economyJS.js'. + +'slaveJobValues()' takes into account gloryholes/arcade, public sluts/club sluts and street whores/brothel whores seperately. +Gloryhole prices aren't too involved, since the 'product' is very homogenous and sluts don't get paid for their services. +Whores on the other hand have variable skills and appearance and may appeal to different classes of citizens. + +'SJVBrothel()' takes care of general bonuses/penalties that all jobs have to some degree. +Near the end it determines the 'value' of the whore by taking the above bonus, their 'beauty()' and their 'FResult()' score. +Previously 'beauty()' determined the number of sexual acts and 'FResult()' the price for them. +With the distinction between classes and the kind of sexual services they demand it became glaring that the best quality whores were used most heavily. +Shouldn't these talented slaves should be MORE exclusive, not less? + +The function whoreScore() will be taking care of this oddity and it uses 'beauty()' * 'FResult()' as well as applicable modifiers to give us an 'income' variable. +This 'income' is the basis for the money the slave will be making, but will still be going through some modifications before the actual figure is produced later. +This is the amount of money they used to make and are still expected to make under standard circumstances but now it will be divided between sexual acts and their value in a different fashion. +whoreScore() also takes care of some slave sorting according to supply and demand. +Whenever the demand of the class a slave is trying to service is already met the function will determine if the slave should perhaps service a lower class instead. +It uses effectiveWhoreClass() to find out the maximum possible class a slave can service (or is allowed to service by the player), and demotes a slave for the week as needed. +After the class of citizens the slave will service is set the function takes care of the specific 'sexAmount' and 'sexQuality' the slave is providing. +The higher the class the more time and attention they demand from their whores. Generally a better slave servicing a higher class will fuck less than a lesser slave servicing a lower class. +The price per service is adjusted to compensate; 'income' is the basis, 'sexAmount' is partially set by the class serviced and 'sexQuality' is 'income' / 'sexAmount'. +There is a maximum for the 'sexAmount' and 'sexQuality' for each class; On the one hand the slave only has so much time in the day and on the other citizens will only pay a particular amount of money. +There is also a minimum for 'sexAmount'; a slave assigned to whore is expected to be working hard for the entire assignment, if needed the price will be adjusted to ensure a full work week for every slave. +The maximum amount of money a citizen is willing to pay depends on the rent they need to pay. Less rent means they have more spending money for other things, including whores. +Additionally servicing a higher class also comes with a little bonus in and of itself. + +'slaveJobValues()' aggregates all sexual services done by a player's slaves, thus at the end of this function we know the supply provided by the player. +We must also consider the supply by other providers operating within the arcology, but this is relatively straightforward. +Combine the two and we now have the total supply for that week and we can finally compare supply and demand to provide a final price modifier. +Each class of citizens has their own demand and supply statistics and thus their own price modifier as well. +All of this once again takes place within the top part of 'slaveAssignmentsReport.tw'. +When demand outstrips supply, a whore will recieve a premium for their services, but not proportionally. +Supplying only half of what is demanded does not mean prices are doubled, they'll be increased by less than that. +Likewise when supply outstrips the demand a whore will recieve less for their services, but not proportionally. +Doubling the demand reduces the price by significantly more than 50%. +There is however an absolute minimum of 30% of the standard price. + +Finally, as each slave has their report generated they will actually be earning 'sexAmount' * 'sexQuality' * supply/demand modifier. \ No newline at end of file diff --git a/src/js/economyJS.js b/src/js/economyJS.js index 0b4687f1d74f1fa76e7285fe2cad6c243cd3aecc..65ffa9c4653a7c55fe2d7c6d9ba8d048b4ef2a86 100644 --- a/src/js/economyJS.js +++ b/src/js/economyJS.js @@ -1745,6 +1745,8 @@ window.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDemandRef */ function whoreScore(s, lowerClassSexDemandRef, middleClassSexDemandRef, upperClassSexDemandRef, topClassSexDemandRef) { let income = s.sexAmount * s.sexQuality; + let sexMin; + let sexBudget; const initialHealthPenalty = healthPenalty(s); s.effectiveWhoreClass = effectiveWhoreClass(s); s.maxWhoreClass = s.effectiveWhoreClass; @@ -1773,37 +1775,69 @@ window.slaveJobValues = function(lowerClassSexDemandRef, middleClassSexDemandRef // Calculate the stats if (s.effectiveWhoreClass === 4) { - s.sexAmount = Math.clamp(Math.trunc(s.sexAmount * (1 / 3)), normalRandInt(30, 2), normalRandInt(60, 3)); // Bringing sex amount into the desired range. Beauty improves use amount between values of aprox. 90 and 180. + sexMin = normalRandInt(30, 2); // The minimum of fucks per week; can increase if needed + sexBudget = Math.trunc(V.whoreBudget.topClass * 0.2); // initial maximum price per fuck; can increase if needed + while (income > sexBudget * sexMin) { // if the income can not be caught within the initial values of sexMin and sexBudget we increase both as needed in this loop + sexMin = Math.trunc(sexMin * 1.1); + if (income > sexBudget * sexMin) { + sexBudget = Math.trunc(sexBudget * 1.1); + } + } + s.sexAmount = sexMin; tiredFucks(s); // adding tiredness based on number of fucks and then adjusting income in case the tiredness penalty changed as a result. if (healthPenalty(s) < initialHealthPenalty) { income *= healthPenalty(s) / initialHealthPenalty; } - s.sexQuality = Math.min(Math.trunc(Math.min((income * 1.2) / s.sexAmount, V.whoreBudget.topClass * 0.2)), Math.trunc(V.whoreBudget.topClass * (1 / 3))); // Adjusting the price to the correct sex amount with 20% bonus for being of the highest tier. The top class will pay a maximum of 33% of their weekly budget per service. - slaveJobValues.brothel.topClass += Math.trunc(Math.min(s.sexAmount * s.sexQuality, s.sexAmount * V.whoreBudget.topClass * 0.2)); // Registering the job value in the right slot + s.sexQuality = Math.trunc(income / s.sexAmount); + slaveJobValues.brothel.topClass += s.sexAmount * s.sexQuality; // Registering the job value in the right slot } else if (s.effectiveWhoreClass === 3) { - s.sexAmount = Math.clamp(Math.trunc(s.sexAmount * (2 / 3)), normalRandInt(40, 3), normalRandInt(80, 3)); // Beauty improves use amount between values of aprox. 60 and 120. + sexMin = normalRandInt(40, 3); + sexBudget = Math.trunc(V.whoreBudget.upperClass * 0.5); + while (income > sexBudget * sexMin) { + sexMin = Math.trunc(sexMin * 1.1); + if (income > sexBudget * sexMin) { + sexBudget = Math.trunc(sexBudget * 1.1); + } + } + s.sexAmount = sexMin; tiredFucks(s); if (healthPenalty(s) < initialHealthPenalty) { income *= healthPenalty(s) / initialHealthPenalty; } - s.sexQuality = Math.min(Math.trunc((income * 1.05) / s.sexAmount), V.whoreBudget.upperClass * 0.5); // The upper class will pay a maximum of 50% of their weekly budget per service - slaveJobValues.brothel.upperClass += Math.trunc(Math.min(s.sexAmount * s.sexQuality, s.sexAmount * V.whoreBudget.upperClass * 0.6)); + s.sexQuality = Math.trunc(income / s.sexAmount); + slaveJobValues.brothel.upperClass += s.sexAmount * s.sexQuality; } else if (s.effectiveWhoreClass === 2) { - s.sexAmount = Math.clamp(Math.trunc(s.sexAmount * 1.25), normalRandInt(50, 3), normalRandInt(120, 3)); // Beauty improves use amount between values of aprox. 40 and 96. + sexMin = normalRandInt(50, 3); + sexBudget = V.whoreBudget.middleClass; + while (income > sexBudget * sexMin) { + sexMin = Math.trunc(sexMin * 1.1); + if (income > sexBudget * sexMin) { + sexBudget = Math.trunc(sexBudget * 1.1); + } + } + s.sexAmount = sexMin; tiredFucks(s); if (healthPenalty(s) < initialHealthPenalty) { income *= healthPenalty(s) / initialHealthPenalty; } - s.sexQuality = Math.min(Math.trunc((income * 0.9) / s.sexAmount), V.whoreBudget.middleClass); // The middle class will pay a maximum of 125% of their weekly budget per service - slaveJobValues.brothel.middleClass += Math.trunc(Math.min(s.sexAmount * s.sexQuality, s.sexAmount * V.whoreBudget.middleClass * 1.25)); + s.sexQuality = Math.trunc(income / s.sexAmount); + slaveJobValues.brothel.middleClass += s.sexAmount * s.sexQuality; } else { - s.sexAmount = Math.clamp(s.sexAmount * 2, normalRandInt(60, 3), normalRandInt(150, 3)); // Beauty improves use amount between values of approx. 30 and 75. + sexMin = normalRandInt(60, 3); + sexBudget = V.whoreBudget.lowerClass * 3; + while (income > sexBudget * sexMin) { + sexMin = Math.trunc(sexMin * 1.1); + if (income > sexBudget * sexMin) { + sexBudget = Math.trunc(sexBudget * 1.1); + } + } + s.sexAmount = sexMin; tiredFucks(s); if (healthPenalty(s) < initialHealthPenalty) { income *= healthPenalty(s) / initialHealthPenalty; } - s.sexQuality = Math.clamp(Math.trunc((income * 0.75) / s.sexAmount), 2, V.whoreBudget.lowerClass * 3); // The lower class will pay a maximum of 300% of their weekly budget per service and a minimum of 2 - slaveJobValues.brothel.lowerClass += Math.trunc(Math.min(s.sexAmount * s.sexQuality, s.sexAmount * V.whoreBudget.lowerClass * 3)); + s.sexQuality = Math.max(Math.trunc(income / s.sexAmount), 2); // The lower class will pay a minimum of 2 per fuck + slaveJobValues.brothel.lowerClass += s.sexAmount * s.sexQuality; } } diff --git a/src/uncategorized/slaveAssignmentsReport.tw b/src/uncategorized/slaveAssignmentsReport.tw index 688efe2c848ac5fdae2b6adc2698ee5b202c849e..e3bd7d82932186e8365f43859c682e27bd61cf48 100644 --- a/src/uncategorized/slaveAssignmentsReport.tw +++ b/src/uncategorized/slaveAssignmentsReport.tw @@ -28,14 +28,14 @@ Depending on the conditions they may derive more or less 'utility' out of their credits spent i.e. a highly paternalist arcology with little choice for its lower class but Fuckdolls may still put money into them but not get the same satisfaction out of it*/ /*Low rent increases demand/available money for sexual services, high rent decreases it*/ -<<set _lowerClassSexDemand = Math.trunc($lowerClass * $whoreBudget.lowerClass), +<<set _lowerClassSexDemand = Math.trunc($lowerClass * $whoreBudget.lowerClass) * 2, _lowerClassSexDemandRef = Math.max(_lowerClassSexDemand, 1), _visitorsSexDemand = Math.trunc($visitors) * 40, -_middleClassSexDemand = Math.trunc($middleClass * $whoreBudget.middleClass + _visitorsSexDemand * 0.5), -_middleClassSexDemandRef = Math.max(_middleClassSexDemand + Math.trunc(_visitorsSexDemand * 0.5), 1), -_upperClassSexDemand = Math.trunc($upperClass * $whoreBudget.upperClass + _visitorsSexDemand * 0.5), -_upperClassSexDemandRef = Math.max(_upperClassSexDemand + Math.trunc(_visitorsSexDemand * 0.5), 1), -_topClassSexDemand = Math.trunc($topClass * $whoreBudget.topClass), +_middleClassSexDemand = Math.trunc($middleClass * $whoreBudget.middleClass + _visitorsSexDemand * 0.5) * 2, +_middleClassSexDemandRef = Math.max(_middleClassSexDemand, 1), +_upperClassSexDemand = Math.trunc($upperClass * $whoreBudget.upperClass + _visitorsSexDemand * 0.5) * 2, +_upperClassSexDemandRef = Math.max(_upperClassSexDemand, 1), +_topClassSexDemand = Math.trunc($topClass * $whoreBudget.topClass) * 2, _topClassSexDemandRef = Math.max(_topClassSexDemand, 1), _arcadeSupply = {lowerClass: 0, middleClass: 0, upperClass: 0}, _clubSupply = {lowerClass: 0, middleClass: 0}, @@ -107,31 +107,31 @@ _clubSupply.middleClass = Math.trunc($slaveJobValues.club * $slaveJobValues.club /*Brothel or street whore sex supply*/ <<if _lowerClassSexDemand < $slaveJobValues.brothel.lowerClass>> - <<set $whorePriceAdjustment.lowerClass = Math.max(Math.pow(_lowerClassSexDemand / ($slaveJobValues.brothel.lowerClass + $NPCSexSupply.lowerClass), 2), 0.25), + <<set $whorePriceAdjustment.lowerClass = Math.max(Math.pow(_lowerClassSexDemand / ($slaveJobValues.brothel.lowerClass + $NPCSexSupply.lowerClass), 1.513), 0.3), _lowerClassSexDemand = 0>> /*This accounts for people having too much choice and getting more picky how they spend their money*/ <<else>> - <<set $whorePriceAdjustment.lowerClass = Math.pow(_lowerClassSexDemand / ($slaveJobValues.brothel.lowerClass + $NPCSexSupply.lowerClass), 0.25), + <<set $whorePriceAdjustment.lowerClass = Math.pow(_lowerClassSexDemand / ($slaveJobValues.brothel.lowerClass + $NPCSexSupply.lowerClass), 0.5), _lowerClassSexDemand -= $slaveJobValues.brothel.lowerClass>> /* People are willing to pay more for a scarce good, but within reason */ <</if>> <<if _middleClassSexDemand < $slaveJobValues.brothel.middleClass>> - <<set $whorePriceAdjustment.middleClass = Math.max(Math.pow(_middleClassSexDemand / ($slaveJobValues.brothel.middleClass + $NPCSexSupply.middleClass), 2), 0.25), + <<set $whorePriceAdjustment.middleClass = Math.max(Math.pow((_middleClassSexDemand * 1.1) / ($slaveJobValues.brothel.middleClass + $NPCSexSupply.middleClass), 1.513), 0.33), _middleClassSexDemand = 0>> <<else>> - <<set $whorePriceAdjustment.middleClass = Math.pow(_middleClassSexDemand / ($slaveJobValues.brothel.middleClass + $NPCSexSupply.middleClass), 0.25), + <<set $whorePriceAdjustment.middleClass = Math.pow((_middleClassSexDemand * 1.1) / ($slaveJobValues.brothel.middleClass + $NPCSexSupply.middleClass), 0.5), _middleClassSexDemand -= $slaveJobValues.brothel.middleClass>> <</if>> <<if _upperClassSexDemand < $slaveJobValues.brothel.upperClass>> - <<set $whorePriceAdjustment.upperClass = Math.max(Math.pow(_upperClassSexDemand / ($slaveJobValues.brothel.upperClass + $NPCSexSupply.upperClass), 2), 0.25), + <<set $whorePriceAdjustment.upperClass = Math.max(Math.pow((_upperClassSexDemand * 1.21) / ($slaveJobValues.brothel.upperClass + $NPCSexSupply.upperClass), 1.513), 0.363), _upperClassSexDemand = 0>> <<else>> - <<set $whorePriceAdjustment.upperClass = Math.pow(_upperClassSexDemand / ($slaveJobValues.brothel.upperClass + $NPCSexSupply.upperClass), 0.25), + <<set $whorePriceAdjustment.upperClass = Math.pow((_upperClassSexDemand * 1.21) / ($slaveJobValues.brothel.upperClass + $NPCSexSupply.upperClass), 0.5), _upperClassSexDemand -= $slaveJobValues.brothel.upperClass>> <</if>> <<if _topClassSexDemand < $slaveJobValues.brothel.topClass>> - <<set $whorePriceAdjustment.topClass = Math.max(Math.pow(_topClassSexDemand / ($slaveJobValues.brothel.topClass + $NPCSexSupply.topClass), 2), 0.25), + <<set $whorePriceAdjustment.topClass = Math.max(Math.pow((_topClassSexDemand * 1.331) / ($slaveJobValues.brothel.topClass + $NPCSexSupply.topClass), 1.513), 0.3993), _topClassSexDemand = 0>> <<else>> - <<set $whorePriceAdjustment.topClass = Math.pow(_topClassSexDemand / ($slaveJobValues.brothel.topClass + $NPCSexSupply.topClass), 0.25), + <<set $whorePriceAdjustment.topClass = Math.pow((_topClassSexDemand * 1.331) / ($slaveJobValues.brothel.topClass + $NPCSexSupply.topClass), 0.5), _topClassSexDemand -= $slaveJobValues.brothel.topClass>> <</if>>