further tweak gang script
This commit is contained in:
parent
166bf73c1a
commit
253d4d029a
|
@ -4,21 +4,21 @@ export async function main(ns) {
|
||||||
ns.tail()
|
ns.tail()
|
||||||
ns.disableLog('ALL')
|
ns.disableLog('ALL')
|
||||||
|
|
||||||
// config
|
/** CCONFIG **/
|
||||||
/* Maximum number of members in a gang */
|
/* Maximum number of members in a gang */
|
||||||
const MAX_MEMBER_COUNT = 12
|
const MAX_MEMBER_COUNT = 12
|
||||||
/* Percent of training to the next ascension a member must do after ascending */
|
/* Percent of training to the next ascension a member must do after ascending */
|
||||||
const MIN_ASCENSION_PERCENT = 0.9
|
const MIN_ASCENSION_PERCENT = 0.95
|
||||||
/* Minimum power level a member must reach before transitioning to gang war/money making */
|
/* Minimum power level a member must reach before transitioning to gang war/money making */
|
||||||
const MIN_POWER_LEVEL = 15
|
const MIN_POWER_LEVEL = 15
|
||||||
/* Win chance required to start a gang war */
|
/* Minimum win chance required to start a gang war */
|
||||||
const GANG_WAR_START_TRESH = 0.6
|
const GANG_WAR_START_TRESH = 0.6
|
||||||
/* Minimum win chance before pulling out of a gang war */
|
/* Minimum win chance before pulling out of a gang war */
|
||||||
const GANG_WAR_STOP_TRESH = 0.55
|
const GANG_WAR_STOP_TRESH = 0.55
|
||||||
/* Target win chance */
|
/* Target win chance */
|
||||||
const GANG_WAR_TARGET = 0.9
|
const GANG_WAR_TARGET = 0.95
|
||||||
|
|
||||||
// enum
|
/** CONSTANTS **/
|
||||||
const MAKE_MONEY = "Human Trafficking"
|
const MAKE_MONEY = "Human Trafficking"
|
||||||
const VIGILANTE_JUSTICE = "Vigilante Justice"
|
const VIGILANTE_JUSTICE = "Vigilante Justice"
|
||||||
const MUG_PEOPLE = "Mug People"
|
const MUG_PEOPLE = "Mug People"
|
||||||
|
@ -28,8 +28,9 @@ export async function main(ns) {
|
||||||
|
|
||||||
const PHASE_CATCHUP = "catchup"
|
const PHASE_CATCHUP = "catchup"
|
||||||
const PHASE_RECRUIT = "recruit"
|
const PHASE_RECRUIT = "recruit"
|
||||||
const PHASE_WAR = "war"
|
const PHASE_TRAIN = "train"
|
||||||
const PHASE_MONEY = "money"
|
const PHASE_WAR = "gang war"
|
||||||
|
const PHASE_MONEY = "make money"
|
||||||
|
|
||||||
const memberNamePool = [
|
const memberNamePool = [
|
||||||
"CJ",
|
"CJ",
|
||||||
|
@ -119,7 +120,6 @@ export async function main(ns) {
|
||||||
|
|
||||||
// Credit: Mysteyes. https://discord.com/channels/415207508303544321/415207923506216971/940379724214075442
|
// Credit: Mysteyes. https://discord.com/channels/415207508303544321/415207923506216971/940379724214075442
|
||||||
function getAscendTreshold(memberName) {
|
function getAscendTreshold(memberName) {
|
||||||
const memberInfo = ns.gang.getMemberInformation(memberName)
|
|
||||||
const mult = getMinAscMult(memberName)
|
const mult = getMinAscMult(memberName)
|
||||||
if (mult < 1.632) return 1.6326;
|
if (mult < 1.632) return 1.6326;
|
||||||
if (mult < 2.336) return 1.4315;
|
if (mult < 2.336) return 1.4315;
|
||||||
|
@ -137,14 +137,11 @@ export async function main(ns) {
|
||||||
return 1.0591;
|
return 1.0591;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isAscensionReady(memberName) {
|
function isRecruitmentReady(power, memberCount) {
|
||||||
return getMinAscensionResult(memberName) >= getAscendTreshold(memberName)
|
// the formula here is kinda arbitrary
|
||||||
}
|
// increase the number of members in the gang linearly with the power of its members
|
||||||
|
// ns.print(power * 1.5 + 3)
|
||||||
function isRecruitementReady(relativePower, memberCount) {
|
return power * 1.5 + 3 > memberCount
|
||||||
const res = relativePower * 1.25 + 2 > memberCount // TODO
|
|
||||||
ns.print(relativePower * 1.25 + 2)
|
|
||||||
return res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGangWarWinChance() {
|
function getGangWarWinChance() {
|
||||||
|
@ -158,106 +155,109 @@ export async function main(ns) {
|
||||||
while (true) {
|
while (true) {
|
||||||
const gangInfo = ns.gang.getGangInformation()
|
const gangInfo = ns.gang.getGangInformation()
|
||||||
|
|
||||||
ns.print("running loop")
|
|
||||||
|
|
||||||
// check for and recruit new members if available
|
// check for and recruit new members if available
|
||||||
while (ns.gang.canRecruitMember()) {
|
while (ns.gang.canRecruitMember()) {
|
||||||
const availableNames = memberNamePool.filter(x => memberNamePool.includes(x))
|
const availableNames = memberNamePool.filter(x => memberNamePool.includes(x))
|
||||||
const memberName = availableNames[Math.floor(Math.random() * availableNames.length)]
|
const memberName = availableNames[Math.floor(Math.random() * availableNames.length)]
|
||||||
ns.gang.recruitMember(memberName)
|
ns.gang.recruitMember(memberName)
|
||||||
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
|
||||||
}
|
|
||||||
|
|
||||||
const gangMembers = ns.gang.getMemberNames()
|
|
||||||
|
|
||||||
// check for and ascend members who are ready
|
|
||||||
for (const memberName of gangMembers) {
|
|
||||||
if (isAscensionReady(memberName)) {
|
|
||||||
// ns.print("ascending " + memberName)
|
|
||||||
ns.gang.ascendMember(memberName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// gang war
|
// gang war
|
||||||
if (getGangWarWinChance() >= GANG_WAR_START_TRESH) {
|
const gangWarWinChance = getGangWarWinChance()
|
||||||
|
if (gangWarWinChance >= GANG_WAR_START_TRESH) {
|
||||||
// go to war
|
// go to war
|
||||||
ns.gang.setTerritoryWarfare(true)
|
ns.gang.setTerritoryWarfare(true)
|
||||||
}
|
}
|
||||||
else if (getGangWarWinChance() <= GANG_WAR_STOP_TRESH) {
|
else if (gangWarWinChance <= GANG_WAR_STOP_TRESH) {
|
||||||
// disengage
|
// disengage
|
||||||
ns.gang.setTerritoryWarfare(false)
|
ns.gang.setTerritoryWarfare(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// score each member by their estimated power level
|
// create an 2-dimensional array of member data. We use an array because we need it to be sorted
|
||||||
let memberDatas = gangMembers.map(x => [x, {
|
// 1st dimension is for each member
|
||||||
"relativePower": estimateMemberPower(x),
|
// index 0 of 2nd dimension is the name of the member
|
||||||
|
// index 1 of 2nd dimension is the data
|
||||||
|
let gangMembers = ns.gang.getMemberNames().map(x => [x, {
|
||||||
|
"power": estimateMemberPower(x),
|
||||||
"minSkillLevel": getMinSkillLevel(x),
|
"minSkillLevel": getMinSkillLevel(x),
|
||||||
"ascensionPercent": getMinAscensionResult(x) / getAscendTreshold(x),
|
"ascensionPercent": getMinAscensionResult(x) / getAscendTreshold(x),
|
||||||
"phase": undefined,
|
"phase": undefined,
|
||||||
"training": false,
|
"training": false,
|
||||||
"vigilante": false,
|
"vigilante": false,
|
||||||
}])
|
}])
|
||||||
memberDatas.sort((a, b) => b[1]["relativePower"] - a[1]["relativePower"])
|
// sort by their power
|
||||||
const targetRelativePower = memberDatas[0][1]["relativePower"] - 2
|
gangMembers.sort((a, b) => b[1]["power"] - a[1]["power"])
|
||||||
|
// the highest power level is the target new members needs to catchup to
|
||||||
for (const memberData of memberDatas) {
|
const targetPower = gangMembers[0][1]["power"] - 2
|
||||||
const memberName = memberData[0]
|
// check if we are ready to recruit a new member
|
||||||
const relativePower = memberData[1]["relativePower"]
|
const recruitmentReady = isRecruitmentReady(targetPower, gangMembers.length)
|
||||||
const minSkillLevel = memberData[1]["minSkillLevel"]
|
|
||||||
const ascensionPercent = memberData[1]["ascensionPercent"]
|
|
||||||
|
|
||||||
|
for (const member of gangMembers) {
|
||||||
|
const memberName = member[0]
|
||||||
|
const memberData = member[1]
|
||||||
|
const power = memberData["power"]
|
||||||
|
const minSkillLevel = memberData["minSkillLevel"]
|
||||||
|
const ascensionPercent = memberData["ascensionPercent"]
|
||||||
|
|
||||||
// compute the phase of each members
|
// compute the phase of each members
|
||||||
if (relativePower < targetRelativePower) {
|
if (power < targetPower) {
|
||||||
// bring up newcomers to the same level than established members
|
// bring up newcomers to the same level than established members
|
||||||
memberData[1]["phase"] = PHASE_CATCHUP
|
memberData["phase"] = PHASE_CATCHUP
|
||||||
}
|
}
|
||||||
else if (gangMembers.length < MAX_MEMBER_COUNT && isRecruitementReady(targetRelativePower, gangMembers.length)) {
|
else if (gangMembers.length < MAX_MEMBER_COUNT) {
|
||||||
// gain respect to recruit new member
|
// gain respect to recruit new member
|
||||||
memberData[1]["phase"] = PHASE_RECRUIT
|
memberData["phase"] = PHASE_RECRUIT
|
||||||
}
|
}
|
||||||
else if (gangInfo.territory < 1 && getGangWarWinChance() < GANG_WAR_TARGET) {
|
else if (power < MIN_POWER_LEVEL) {
|
||||||
|
// power up until useful enough
|
||||||
|
memberData["phase"] = PHASE_TRAIN
|
||||||
|
}
|
||||||
|
else if (gangInfo.territory < 1 && gangWarWinChance < GANG_WAR_TARGET) {
|
||||||
// prepare for gang war
|
// prepare for gang war
|
||||||
memberData[1]["phase"] = PHASE_WAR
|
memberData["phase"] = PHASE_WAR
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if everything else is done, make money
|
// if everything else is done, make money
|
||||||
memberData[1]["phase"] = PHASE_MONEY
|
memberData["phase"] = PHASE_MONEY
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memberData[1]["phase"] == PHASE_CATCHUP) {
|
// assign tasks
|
||||||
|
// strategy is:
|
||||||
|
// catchup -> recruit <-> train -> gang war <-> make money
|
||||||
|
// reduce wanted level as needed
|
||||||
|
if (memberData["phase"] == PHASE_CATCHUP) {
|
||||||
ns.print("assignment: catchup")
|
ns.print("assignment: catchup")
|
||||||
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
||||||
memberData[1]["training"] = true
|
memberData["training"] = true
|
||||||
}
|
}
|
||||||
else if (ascensionPercent < MIN_ASCENSION_PERCENT) { // TODO: arbitrary constant to be ajusted
|
else if (isNaN(ascensionPercent) || ascensionPercent < MIN_ASCENSION_PERCENT) { // TODO: arbitrary constant to be ajusted
|
||||||
ns.print("assignment: level up after ascension")
|
ns.print("assignment: level up after ascension")
|
||||||
// train a member back up after ascention
|
// train a member back up after ascention
|
||||||
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
||||||
memberData[1]["training"] = true
|
memberData["training"] = true
|
||||||
}
|
}
|
||||||
else if (gangInfo.wantedPenalty < 0) {
|
else if (gangInfo.wantedPenalty < 0) {
|
||||||
ns.print("assignment: reduce wanted level")
|
ns.print("assignment: reduce wanted level")
|
||||||
// try to keep the wanted penalty at 0%
|
// try to keep the wanted penalty at 0%
|
||||||
ns.gang.setMemberTask(memberName, VIGILANTE_JUSTICE)
|
ns.gang.setMemberTask(memberName, VIGILANTE_JUSTICE)
|
||||||
memberData[1]["vigilante"] = true
|
memberData["vigilante"] = true
|
||||||
}
|
}
|
||||||
else if (memberData[1]["phase"] == PHASE_RECRUIT) {
|
else if (memberData["phase"] == PHASE_RECRUIT && recruitmentReady) {
|
||||||
ns.print("assignment: gain respect to recruit new members")
|
ns.print("assignment: gain respect to recruit new members")
|
||||||
if (minSkillLevel < 500) {
|
if (minSkillLevel < 250) {
|
||||||
ns.gang.setMemberTask(memberName, MUG_PEOPLE)
|
ns.gang.setMemberTask(memberName, MUG_PEOPLE)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ns.gang.setMemberTask(memberName, TERRORISM)
|
ns.gang.setMemberTask(memberName, TERRORISM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (relativePower < MIN_POWER_LEVEL) {
|
else if (memberData["phase"] == PHASE_RECRUIT || memberData["phase"] == PHASE_TRAIN) {
|
||||||
ns.print("assignment: train")
|
ns.print("assignment: train")
|
||||||
// train up to next ascention
|
// train up to next ascention
|
||||||
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
ns.gang.setMemberTask(memberName, TRAIN_COMBAT)
|
||||||
memberData[1]["training"] = true
|
memberData["training"] = true
|
||||||
}
|
}
|
||||||
else if (memberData[1]["phase"] == PHASE_WAR) {
|
else if (memberData["phase"] == PHASE_WAR) {
|
||||||
ns.print("assignment: gang war")
|
ns.print("assignment: gang war")
|
||||||
ns.gang.setMemberTask(memberName, TERRITORY_WARFARE)
|
ns.gang.setMemberTask(memberName, TERRITORY_WARFARE)
|
||||||
}
|
}
|
||||||
|
@ -267,14 +267,20 @@ export async function main(ns) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// buy equipement
|
// buy equipement
|
||||||
if (memberData[1]["phase"] == PHASE_WAR || memberData[1]["phase"] == PHASE_MONEY) {
|
if (memberData["phase"] == PHASE_WAR || memberData["phase"] == PHASE_MONEY) {
|
||||||
for (const equipment of equipments) {
|
for (const equipment of equipments) {
|
||||||
ns.gang.purchaseEquipment(memberName, equipment)
|
ns.gang.purchaseEquipment(memberName, equipment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ns.print(getMinAscensionResult(memberName) / getAscendTreshold(memberName))
|
|
||||||
|
// ascend members who are ready
|
||||||
|
if (ascensionPercent >= 1 &&
|
||||||
|
!(memberData["phase"] == PHASE_RECRUIT && memberData["training"] == false)) { // avoid ascending a member that has built up respect to recruit a new member
|
||||||
|
// ns.print("ascending " + memberName)
|
||||||
|
ns.gang.ascendMember(memberName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ns.print(memberDatas)
|
ns.print(gangMembers)
|
||||||
await ns.sleep(5000)
|
await ns.sleep(5000)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/** @param {NS} ns */
|
||||||
|
export async function main(ns) {
|
||||||
|
ns.clearLog()
|
||||||
|
ns.tail()
|
||||||
|
ns.disableLog('sleep')
|
||||||
|
|
||||||
|
const START_SKILL_LEVEL = 80
|
||||||
|
const GYM_NAME = "powerhouse gym"
|
||||||
|
const FACTION = "Slum Snakes"
|
||||||
|
|
||||||
|
const skills = [
|
||||||
|
"strength",
|
||||||
|
"defense",
|
||||||
|
"dexterity",
|
||||||
|
"agility"
|
||||||
|
]
|
||||||
|
|
||||||
|
// skillup
|
||||||
|
for (const skill of skills) {
|
||||||
|
let player = ns.getPlayer()
|
||||||
|
if (player.skills[skill] < START_SKILL_LEVEL) {
|
||||||
|
ns.singularity.gymWorkout(GYM_NAME, skill, ns.singularity.isFocused())
|
||||||
|
while(player.skills[skill] < START_SKILL_LEVEL) {
|
||||||
|
await ns.sleep(1000)
|
||||||
|
player = ns.getPlayer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate bad karma
|
||||||
|
ns.singularity.commitCrime("Homicide", ns.singularity.isFocused())
|
||||||
|
|
||||||
|
// join faction
|
||||||
|
if(!ns.getPlayer().factions.includes(FACTION)) {
|
||||||
|
while(!ns.singularity.checkFactionInvitations().includes(FACTION)) {
|
||||||
|
await ns.sleep(1000)
|
||||||
|
}
|
||||||
|
ns.singularity.joinFaction(FACTION)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create gang
|
||||||
|
while(!ns.gang.inGang()) {
|
||||||
|
await ns.sleep(1000)
|
||||||
|
ns.gang.createGang(FACTION)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start gang management script
|
||||||
|
ns.singularity.commitCrime("Kidnap", ns.singularity.isFocused())
|
||||||
|
ns.spawn("/gang/gang-manage.js")
|
||||||
|
}
|
Loading…
Reference in New Issue