bug fixes, add logic for random bait selection
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
###############################################
|
||||||
|
Prompt to Kiro AI (Default):
|
||||||
|
|
||||||
|
In pickRandomCreature, I want to smooth out the probabilities of picking a creature. normally, I could just do total-difficulty / total to get a chance for each one, but I want my selection to be slightly smoother, so that rarer fish are easier to catch (only once unlocked, of course, but that is already checked in possibilties list). what approach could you reccomend?
|
||||||
|
|
||||||
|
Response:
|
||||||
|
|
||||||
|
You want to compress the spread between common and rare weights. The standard trick is to transform each weight before normalizing, rather than using raw difficulty.
|
||||||
|
|
||||||
|
Power/exponent smoothing — raise each weight to a power between 0 and 1:
|
||||||
|
|
||||||
|
|
||||||
|
weight = difficulty ** k # k = 0.5 (sqrt) is a good start
|
||||||
|
k = 1 → unchanged
|
||||||
|
k = 0.5 → square root, pulls rare fish up noticeably
|
||||||
|
k → 0 → approaches uniform (everything equally likely)
|
||||||
|
One knob (k) tunes the whole curve, which is nice for playtesting.
|
||||||
|
|
||||||
|
Alternatives if you want finer control:
|
||||||
|
|
||||||
|
Additive floor: weight = difficulty + c. Adding a constant to every fish shrinks the ratio between big and small, so rares get a flat boost. Simple but less tunable than the exponent.
|
||||||
|
Invert first: if higher difficulty should mean rarer, remember raw difficulty makes hard fish more likely. You may want weight = (1 / difficulty) ** k or (maxDiff - difficulty + 1) depending on which direction "rare" means for you.
|
||||||
|
Mechanically, once you have smoothed weights: sum them, roll random.random() * total, then walk the list subtracting each weight until you cross zero — that's your pick.
|
||||||
|
|
||||||
|
Start with sqrt (k=0.5) and adjust from there.
|
||||||
|
|
||||||
|
###############################################
|
||||||
|
|
||||||
|
Follow up:
|
||||||
|
|
||||||
|
look at my implementation. is that sufficient?
|
||||||
|
|
||||||
|
Response: (wow it found a lot of bugs oops, glad they got caught now)
|
||||||
|
|
||||||
|
Good progress on the logic. The weighting approach in pickRandomCreature is sound, but there are several bugs — some will crash, some are subtle. Grouped by severity:
|
||||||
|
|
||||||
|
Crashers:
|
||||||
|
|
||||||
|
AVAILABLE_BAITS — missing commas between tuples. This is a syntax error (Python tries to call the tuples). Add commas after each.
|
||||||
|
|
||||||
|
pickRandomCreature:
|
||||||
|
|
||||||
|
possibilties is misspelled (vs possibilities) on the total line → NameError.
|
||||||
|
b[0] should be bait[0] in the max_difficulty comprehension.
|
||||||
|
You're comparing bait[0] (the name) but then take bait[0] as max_difficulty — index mismatch. Name is [0], max_difficulty is [1]. You want: filter on bait[0] == current_bait, return bait[1].
|
||||||
|
onAppStart:
|
||||||
|
|
||||||
|
app.waterBottom = app.height = app.waterHeight — double assignment. This overwrites app.height with waterHeight (133). Almost certainly meant app.height - app.waterHeight.
|
||||||
|
Logic bugs:
|
||||||
|
|
||||||
|
The weighted pick is backwards. You pop() from the end of possibilities, but roll was computed starting from the full total. Popping removes items but the roll walks fine mechanically — except possibleCatch leaks out of the loop scope and if roll logic ever lands exactly, it's fragile. The bigger issue: pop() mutates and the final lookup re-scans app.creatures by name. Cleaner to iterate with a for-loop and break, returning the creature directly. Also — you never return catch.
|
||||||
|
|
||||||
|
Smoothing direction. difficulty ** 0.5 still makes harder fish have a higher weight (49 → 7 beats 4 → 2). You said you want rarer fish easier to catch once unlocked — sqrt compresses the gap but hard fish are still more common than easy ones here. If "rare" means hard fish should be the uncommon ones, you want to invert: weight on something like (max_difficulty - difficulty + 1) ** k. Worth confirming which direction you intend.
|
||||||
|
|
||||||
|
Minor:
|
||||||
|
|
||||||
|
resetFishingState has a trailing pass and doesn't reset app.fishingTimer / app.hookedFish (the comment says it should).
|
||||||
|
|
||||||
|
loadSave returns the same defaultState dict object — fine since it's fresh each call, but note json.load success path skips the default-key merge, so an old save missing a new key (e.g. you add a field later) would break downstream. Consider merging into defaults.
|
||||||
|
|
||||||
|
startSkillCheck: random.randrange(...) takes an int; your newLen expression is a float → TypeError. Wrap in int(). Same risk on the newPos divisor if it hits 0 (last bar, numBars - len == 0) → ZeroDivisionError on the final iteration.
|
||||||
|
|
||||||
|
The #TODO about overlap is a real one — your sequential placement mostly prevents it, but the min(newPos, 360-newLen) cap can push a bar back onto the previous one.
|
||||||
|
|
||||||
|
Want me to walk through a corrected version of just pickRandomCreature, or leave it for you to fix?
|
||||||
|
|
||||||
|
###############################################
|
||||||
@@ -100,10 +100,10 @@ AVAILABLE_UPGRADES = [ # (name, bonus_type, bonus_modifier, price)
|
|||||||
]
|
]
|
||||||
|
|
||||||
AVAILABLE_BAITS = [ # (name, max_difficulty)
|
AVAILABLE_BAITS = [ # (name, max_difficulty)
|
||||||
("Worms", 30)
|
("Worms", 30),
|
||||||
("Worms", 50)
|
("Prawns", 50),
|
||||||
("Worms", 70)
|
("Tuna", 70),
|
||||||
("Worms", 100)
|
("Bass", 100)
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ def onAppStart(app):
|
|||||||
app.waterColor = 'midnightBlue'
|
app.waterColor = 'midnightBlue'
|
||||||
app.grassColor = 'seaGreen'
|
app.grassColor = 'seaGreen'
|
||||||
app.waterHeight = app.height // 3
|
app.waterHeight = app.height // 3
|
||||||
app.waterBottom = app.height = app.waterHeight
|
app.waterBottom = app.height - app.waterHeight
|
||||||
app.grassHeight = 20
|
app.grassHeight = 20
|
||||||
app.grassBottom = app.height - app.waterHeight - app.grassHeight
|
app.grassBottom = app.height - app.waterHeight - app.grassHeight
|
||||||
|
|
||||||
@@ -155,6 +155,9 @@ def resetFishingState(app):
|
|||||||
app.skillCheckSpeed = 1
|
app.skillCheckSpeed = 1
|
||||||
app.skillCheckBars = []
|
app.skillCheckBars = []
|
||||||
app.skillCheckFailed = False
|
app.skillCheckFailed = False
|
||||||
|
|
||||||
|
app.hookedFish = None
|
||||||
|
app.fishingTimer = 0
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -164,7 +167,30 @@ def pickRandomCreature(app):
|
|||||||
# weighted toward easier creatures, while still giving rarer/harder ones a
|
# weighted toward easier creatures, while still giving rarer/harder ones a
|
||||||
# real chance (per the spec's "skewed toward easier but still fun" goal).
|
# real chance (per the spec's "skewed toward easier but still fun" goal).
|
||||||
# Returns the chosen creature record (one entry from app.creatures).
|
# Returns the chosen creature record (one entry from app.creatures).
|
||||||
pass
|
max_difficulty = [bait[1] for bait in AVAILABLE_BAITS if bait[0] == app.save["current_bait"]][0]
|
||||||
|
|
||||||
|
#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
|
||||||
|
#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]
|
||||||
|
total = sum([c[1] for c in possibilities])
|
||||||
|
|
||||||
|
#now pick randomly
|
||||||
|
roll = random.random() * (total - 0.0001) # a value between 0 and total (minus a small amount so we ensure the while loop triggers)
|
||||||
|
|
||||||
|
while roll > 0:
|
||||||
|
possibleCatch = possibilities.pop(0)
|
||||||
|
roll -= possibleCatch[1]
|
||||||
|
|
||||||
|
catch = [c for c in app.creatures if c["name"] == possibleCatch[0]][0]
|
||||||
|
return catch
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def startSkillCheck(app, creature):
|
def startSkillCheck(app, creature):
|
||||||
@@ -185,7 +211,8 @@ def startSkillCheck(app, creature):
|
|||||||
lastPos = 0
|
lastPos = 0
|
||||||
lastLen = 0
|
lastLen = 0
|
||||||
while len(app.skillCheckBars) < numBars:
|
while len(app.skillCheckBars) < numBars:
|
||||||
newLen = random.randrange((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")]))
|
#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")])))
|
||||||
#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)
|
||||||
@@ -197,6 +224,8 @@ def startSkillCheck(app, creature):
|
|||||||
lastPos = newPos
|
lastPos = newPos
|
||||||
lastLen = newLen
|
lastLen = newLen
|
||||||
|
|
||||||
|
#speed is set, bars are set, scene is good, should be fine?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user