AI: adjust balance + HUMAN: add time to show the pattern and fix a filename
This commit is contained in:
@@ -5,6 +5,57 @@ Hard fish should be more difficult AND rarer to catch than easy fish (easy = low
|
|||||||
|
|
||||||
Response:
|
Response:
|
||||||
|
|
||||||
|
I have the full picture now. Here's my diagnosis of why it feels unbalanced, and the number changes I'd propose. I won't touch anything until you approve.
|
||||||
|
|
||||||
|
Why it feels broken
|
||||||
|
1. Hard fish barely appear. Your weight is (max_difficulty - difficulty + 1) ** 0.5. With the Bass license (max 100), a difficulty-10 Bone Fish gets weight √91 ≈ 9.5, while the difficulty-100 Hammerhead gets √1 = 1. That's a ~9.5x gap — hard fish are extremely rare. The sqrt was meant to compress this, but subtracting from max_difficulty first re-stretches it. This is the main "I never see hard fish" cause.
|
||||||
|
|
||||||
|
2. The difficulty→skill-check mapping is brutally nonlinear. Bar length is (1 - difficulty/100) * 50:
|
||||||
|
|
||||||
|
Difficulty 10 → ~45° bars (very easy)
|
||||||
|
Difficulty 50 → ~25°
|
||||||
|
Difficulty 90 → ~5° bars
|
||||||
|
Difficulty 100 → 0 → crashes (the error you hit)
|
||||||
|
Meanwhile bar count is difficulty // 10:
|
||||||
|
|
||||||
|
Difficulty 100 → 10 bars, each ~0° wide. Mathematically impossible.
|
||||||
|
Difficulty 90 → 9 bars at ~5°.
|
||||||
|
So the top-tier fish are simultaneously max-count AND min-length — the difficulty hits you twice, multiplicatively. That's your "insanely impossible" fish.
|
||||||
|
|
||||||
|
3. Speed also scales linearly with difficulty on top of both of the above — a third stacking penalty.
|
||||||
|
|
||||||
|
So difficulty attacks length, count, and speed all at once, and the hardest fish round to literally uncatchable.
|
||||||
|
|
||||||
|
Proposed number changes (data/constants only, no logic)
|
||||||
|
A. Rebalance appearance weighting (k in pickRandomCreature) Change the exponent k from 0.5 to 0.75. This keeps hard-fish rarity (you want that) but softens the gap so you actually see them. Hammerhead goes from 1/9.5 odds to roughly 1/5.5 relative to the easiest fish. If you want them rarer, I'd stay nearer 0.6; for more frequent, 0.85.
|
||||||
|
|
||||||
|
B. Fix the length formula's floor (constants in startSkillCheck) The 50 base and the /100 divisor are the levers. I'd propose base 60 and flooring the length so difficulty-100 doesn't hit 0 — but flooring is logic, so instead I can change the formula's constants so the minimum never reaches 0 at difficulty 100: use (1 - difficulty/125) instead of /100. At difficulty 100 that's (1 - 0.8) = 0.2 → 12° bars instead of 0. This also fixes the crash without a logic change.
|
||||||
|
|
||||||
|
C. Soften bar count difficulty // 10 is steep. difficulty // 15 caps the Hammerhead at 6 bars instead of 10, Lobster(80) at 5, Pufferfish(50) at 3. Much more playable.
|
||||||
|
|
||||||
|
D. Creature difficulty spread (optional, in creatures.tsv) Your difficulties cluster at round numbers (10,20,40,50,60,70,80,90,100). That's fine. I'd leave the TSV alone unless you want me to spread them.
|
||||||
|
|
||||||
|
One thing I need you to confirm: proposals A, B, and C each change a number inside a formula. That's technically editing a line of code, not just a standalone constant. You said numbers-only and ask before logic. These are numeric constants embedded in expressions — do you count that as allowed, or do you want to make those edits yourself and have me only touch the standalone constants (AVAILABLE_UPGRADES, AVAILABLE_BAITS, creatures.tsv, the k value)?
|
||||||
|
|
||||||
|
Tell me which scope you want and I'll proceed.
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
Follow Up:
|
||||||
|
|
||||||
|
thats fine to modify - theyre still constants. go ahed and implement changes A, B, and C, and ill playtest the game to see if its more balanced.
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
All three done:
|
||||||
|
|
||||||
|
A — k: 0.5 → 0.75 (hard fish appear more often while staying rarer than easy ones).
|
||||||
|
B — length formula: (1 - difficulty/100) * 50 → (1 - difficulty/125) * 60. Difficulty-100 fish now get ~12° bars instead of 0°, which also kills the randrange(0) crash.
|
||||||
|
C — bar count: difficulty // 10 → difficulty // 15. Hammerhead (100) drops from 10 bars to 6, Lobster (80) to 5, Pufferfish (50) to 3.
|
||||||
|
Quick reference for what the hardest fish now looks like at Bass tier, no upgrades: Hammerhead = 6 bars at ~12° each, speed capped by the existing max(..., 5). Tough but passable.
|
||||||
|
|
||||||
|
One edge case still lurking that I did not touch (it's the logic you asked me to leave alone): the newPos divisor (360 - lastEndPos) // (numBars - len(...)) can still produce randrange(5, 5) if early bars eat most of the circle. Lowering the bar count makes it much less likely, but it's not impossible on a bad roll. Flag it if you hit a crash during playtesting and we can revisit.
|
||||||
|
|
||||||
|
Go ahead and playtest — let me know how the frequency and difficulty feel.
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
@@ -145,6 +145,7 @@ def onAppStart(app):
|
|||||||
app.skillCheckSpeed = 1
|
app.skillCheckSpeed = 1
|
||||||
app.skillCheckBars = [] # tuples of (position, length)
|
app.skillCheckBars = [] # tuples of (position, length)
|
||||||
app.skillCheckFailed = False
|
app.skillCheckFailed = False
|
||||||
|
app.showPatternTimer = 30
|
||||||
|
|
||||||
#FISHING
|
#FISHING
|
||||||
app.fishingTimer = 0
|
app.fishingTimer = 0
|
||||||
@@ -207,6 +208,7 @@ def resetFishingState(app):
|
|||||||
app.skillCheckSpeed = 1
|
app.skillCheckSpeed = 1
|
||||||
app.skillCheckBars = [] # list of tuples of form (position, length)
|
app.skillCheckBars = [] # list of tuples of form (position, length)
|
||||||
app.skillCheckFailed = False
|
app.skillCheckFailed = False
|
||||||
|
app.showPatternTimer = 30
|
||||||
|
|
||||||
app.hookedFish = None
|
app.hookedFish = None
|
||||||
app.fishingTimer = 0
|
app.fishingTimer = 0
|
||||||
@@ -225,7 +227,7 @@ def pickRandomCreature(app):
|
|||||||
print("max difficulty:", max_difficulty)
|
print("max difficulty:", max_difficulty)
|
||||||
|
|
||||||
#here we take the root of the difficulty to represent the weight of that fish, this makes higher difficulty fish easier to catch once unlocked
|
#here we take the root of the difficulty to represent the weight of that fish, this makes higher difficulty fish easier to catch once unlocked
|
||||||
k = 0.5
|
k = 0.75
|
||||||
#invert the difficulty and add one so it avoids zero
|
#invert the difficulty and add one so it avoids zero
|
||||||
possibilities = [(creature["name"], (max_difficulty - creature["difficulty"] + 1) ** k) for creature in app.creatures if creature["difficulty"] <= max_difficulty]
|
possibilities = [(creature["name"], (max_difficulty - creature["difficulty"] + 1) ** k) for creature in app.creatures if creature["difficulty"] <= max_difficulty]
|
||||||
print("possibilities:",possibilities)
|
print("possibilities:",possibilities)
|
||||||
@@ -262,14 +264,14 @@ def startSkillCheck(app, creature):
|
|||||||
|
|
||||||
app.skillCheckSpeed = max(difficulty / fishingPower, 5) #this got INCREDIBLY slow with good upgrades
|
app.skillCheckSpeed = max(difficulty / fishingPower, 5) #this got INCREDIBLY slow with good upgrades
|
||||||
|
|
||||||
numBars = difficulty // 10 - sum([upgrade[2] for upgrade in AVAILABLE_UPGRADES if (upgrade[0] in app.save["owned_upgrades"] and upgrade[1] == "count")])
|
numBars = difficulty // 15 - sum([upgrade[2] for upgrade in AVAILABLE_UPGRADES if (upgrade[0] in app.save["owned_upgrades"] and upgrade[1] == "count")])
|
||||||
numBars = max(numBars, 1)
|
numBars = max(numBars, 1)
|
||||||
|
|
||||||
lastPos = 0
|
lastPos = 0
|
||||||
lastLen = 0
|
lastLen = 0
|
||||||
while len(app.skillCheckBars) < numBars:
|
while len(app.skillCheckBars) < numBars:
|
||||||
#50 is default length, adjust it proportionally to difficulty, then add upgrade length multipliers. also set to int instead of float
|
#50 is default length, adjust it proportionally to difficulty, then add upgrade length multipliers. also set to int instead of float
|
||||||
newLen = random.randrange(int((1 - (difficulty / 100)) * 50 * math.prod([upgrade[2] for upgrade in AVAILABLE_UPGRADES if (upgrade[0] in app.save["owned_upgrades"] and upgrade[1] == "timing")])))
|
newLen = random.randrange(int((1 - (difficulty / 125)) * 60 * math.prod([upgrade[2] for upgrade in AVAILABLE_UPGRADES if (upgrade[0] in app.save["owned_upgrades"] and upgrade[1] == "timing")])))
|
||||||
#take the end of the last bar, and add a random amount between 5 degrees
|
#take the end of the last bar, and add a random amount between 5 degrees
|
||||||
#and the remaining amount to the end divided by the number of bars left
|
#and the remaining amount to the end divided by the number of bars left
|
||||||
lastEndPos = (lastPos + lastLen)
|
lastEndPos = (lastPos + lastLen)
|
||||||
@@ -316,9 +318,12 @@ def onStep(app):
|
|||||||
app.hookedFish = selectedCreature
|
app.hookedFish = selectedCreature
|
||||||
startSkillCheck(app, selectedCreature)
|
startSkillCheck(app, selectedCreature)
|
||||||
case "skill-check":
|
case "skill-check":
|
||||||
app.skillCheckAngle += app.skillCheckSpeed / 6 #this was far too fast
|
if app.showPatternTimer < 1:
|
||||||
if (app.skillCheckAngle > 360):
|
app.skillCheckAngle += app.skillCheckSpeed / 6 #this was far too fast
|
||||||
finishSkillCheck(app)
|
if (app.skillCheckAngle > 360):
|
||||||
|
finishSkillCheck(app)
|
||||||
|
else:
|
||||||
|
app.showPatternTimer -= 1
|
||||||
|
|
||||||
|
|
||||||
def onMousePress(app, mouseX, mouseY):
|
def onMousePress(app, mouseX, mouseY):
|
||||||
@@ -720,6 +725,7 @@ def drawDebug(app):
|
|||||||
activeBait: {app.save["current_bait"]}
|
activeBait: {app.save["current_bait"]}
|
||||||
Angle: {rounded(app.skillCheckAngle)}
|
Angle: {rounded(app.skillCheckAngle)}
|
||||||
NextBar: {app.skillCheckBars[0] if len(app.skillCheckBars) > 0 else "N/A"}
|
NextBar: {app.skillCheckBars[0] if len(app.skillCheckBars) > 0 else "N/A"}
|
||||||
|
showPatternTimer: {rounded(app.showPatternTimer)}
|
||||||
"""
|
"""
|
||||||
debugLines = debugStr.splitlines()
|
debugLines = debugStr.splitlines()
|
||||||
size = 16
|
size = 16
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"cash": 906146.0, "owned_baits": ["Worms", "Prawns", "Tuna", "Bass"], "owned_upgrades": ["Massive Bobber", "Huge Bobber", "Large Bobber", "Medium Bobber", "Galaxy Rod", "Glowing Rod", "Spectral Rod", "Shiny Rod"], "current_bait": "Tuna"}
|
{"cash": 906214.0, "owned_baits": ["Worms", "Prawns", "Tuna", "Bass"], "owned_upgrades": ["Massive Bobber", "Huge Bobber", "Large Bobber", "Medium Bobber", "Galaxy Rod", "Glowing Rod", "Spectral Rod", "Shiny Rod"], "current_bait": "Bass"}
|
||||||
|
Before Width: | Height: | Size: 259 KiB After Width: | Height: | Size: 259 KiB |
Reference in New Issue
Block a user