pish icons im so tired im almost done
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
###############################################
|
||||
Prompt to Kiro AI (Default):
|
||||
|
||||
im getting a list index out of range error very rarely, right as the fishing timer reaches zero and it begins the catching process. any idea what could be causing that? dont fix, explain.
|
||||
|
||||
Response:
|
||||
|
||||
It's almost certainly the pop() loop in pickRandomCreature.
|
||||
|
||||
The loop pops until roll drops to 0 or below. The guard roll = random.random() * (total - 0.0001) is meant to guarantee the roll is always strictly less than total, so the loop empties enough weight before running out of items. But floating-point rounding breaks that guarantee in rare cases.
|
||||
|
||||
Here's the problem: total is the sum of all the individual weights. Due to float accumulation error, sum(weights) is not exactly equal to subtracting those same weights one by one. In the unlucky case where roll lands extremely close to total, you can pop every item in possibilities and roll is still above 0 by a tiny epsilon — then the next .pop() hits an empty list → index out of range.
|
||||
|
||||
The - 0.0001 fudge shrinks the odds but doesn't eliminate them: if the summed total is itself slightly larger than the re-subtracted total, that 0.0001 margin can be smaller than the accumulated error, especially with your sqrt'd weights which are non-round floats.
|
||||
|
||||
Why it's rare and tied to the timer hitting zero: pickRandomCreature only runs at that moment (bite triggers the pick), and it only fails when the random roll lands in that thin top sliver near total. Most rolls land comfortably in the middle, so you almost never see it.
|
||||
|
||||
Side note that makes it worse: you pop() from the end of the list every time, which is fine mechanically, but it means the walk order and the weight order are the same list being mutated — so once it's empty there's no fallback. A for-loop over a fixed list with a final default pick would avoid the empty-list crash entirely.
|
||||
|
||||
###############################################
|
||||
@@ -0,0 +1,10 @@
|
||||
###############################################
|
||||
Prompt to Kiro AI (Default):
|
||||
|
||||
Hard fish should be more difficult AND rarer to catch than easy fish (easy = lower difficulty number). However, im not getting the opportunity to catch a lot of hard fish in the first place, and it really feels like this game isn't very balanced. Can you go ahead and modify any of the numbers you need (but not logic nor code unless absolutely necessary, and you must ask first) to improve the balance, chance, and fairness of the game?
|
||||
|
||||
Response:
|
||||
|
||||
|
||||
|
||||
###############################################
|
||||
@@ -104,11 +104,11 @@ AVAILABLE_UPGRADES = [ # (name, bonus_type, bonus_modifier, price)
|
||||
("Galaxy Rod", "count", 3, 40000)
|
||||
]
|
||||
|
||||
AVAILABLE_BAITS = [ # (name, max_difficulty)
|
||||
("Worms", 30),
|
||||
("Prawns", 50),
|
||||
("Tuna", 70),
|
||||
("Bass", 100)
|
||||
AVAILABLE_BAITS = [ # (name, max_difficulty, price, image_file)
|
||||
("Worms", 30, 0, "worm.png"),
|
||||
("Prawns", 50, 200, "prawn.png"),
|
||||
("Tuna", 70, 1000, "tuna.png"),
|
||||
("Bass", 100, 19410, "bass.png")
|
||||
|
||||
]
|
||||
|
||||
@@ -121,6 +121,8 @@ def onAppStart(app):
|
||||
# - skill-check state placeholders (cursor angle, bars, speed, result)
|
||||
# - app.stepsPerSecond for the game loop cadence
|
||||
# Delegates to the smaller setup helpers below to keep this readable.
|
||||
|
||||
app.debug = True
|
||||
|
||||
#DRAWING CONSTANTS
|
||||
app.width = 600
|
||||
@@ -165,17 +167,34 @@ def onAppStart(app):
|
||||
colInd = 0
|
||||
XDiff = (endX-startX) // 3
|
||||
|
||||
#build upgrade grid
|
||||
for columnType in ["power", "timing", "count"]:
|
||||
upgrades = [u for u in AVAILABLE_UPGRADES if u[1] == columnType]
|
||||
YDiff = (endY-startY) // len(upgrades)
|
||||
for i in range(len(upgrades)):
|
||||
app.INTERACTABLES.append(("upgrade-buy:" + upgrades[i][0],
|
||||
app.INTERACTABLES.insert(0, ("upgrade-buy:" + upgrades[i][0],
|
||||
"shop",
|
||||
startX + XDiff * colInd,
|
||||
startX + XDiff * colInd + XDiff,
|
||||
startY + YDiff * i,
|
||||
startY + YDiff * i + YDiff))
|
||||
startY + YDiff * i + YDiff)) #this used to just be append
|
||||
#but that was causing issues where the shop bounding box was
|
||||
#checked first, then opening the shop gui, and allowing the
|
||||
#player to purchase an upgrade with the same click (not ideal)
|
||||
colInd += 1
|
||||
|
||||
#build bait grid
|
||||
startX = 125
|
||||
startY = 250
|
||||
endX = 475
|
||||
diffX = (endX - startX) // len(AVAILABLE_BAITS)
|
||||
for i in range(len(AVAILABLE_BAITS)):
|
||||
app.INTERACTABLES.insert(0, ("bait-buy:" + AVAILABLE_BAITS[i][0],
|
||||
"shop",
|
||||
startX + diffX * i,
|
||||
startX + diffX * i + diffX,
|
||||
startY,
|
||||
startY + diffX))
|
||||
|
||||
print(app.INTERACTABLES)
|
||||
|
||||
@@ -212,13 +231,17 @@ def pickRandomCreature(app):
|
||||
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)
|
||||
roll = random.random() * (total) # a value between 0 and total
|
||||
|
||||
while roll > 0:
|
||||
possibleCatch = possibilities.pop(0)
|
||||
caughtName = "Aubrey Fish"
|
||||
for possibleCatch in possibilities:
|
||||
roll -= possibleCatch[1]
|
||||
if (roll < 0):
|
||||
caughtName = possibleCatch[0]
|
||||
break
|
||||
|
||||
catch = [c for c in app.creatures if c["name"] == possibleCatch[0]][0]
|
||||
print(caughtName, app.creatures)
|
||||
catch = [c for c in app.creatures if c["name"] == caughtName][0]
|
||||
return catch
|
||||
|
||||
|
||||
@@ -319,6 +342,9 @@ def onMousePress(app, mouseX, mouseY):
|
||||
if name.startswith("upgrade-buy:"):
|
||||
print("buying upgrade", name)
|
||||
buyUpgrade(app, name.split(":")[1])
|
||||
if name.startswith("bait-buy:"):
|
||||
print("buying bait", name)
|
||||
buyBaitLicense(app, name.split(":")[1])
|
||||
|
||||
|
||||
if not interacted and app.scene == "idle":
|
||||
@@ -341,10 +367,14 @@ def onKeyPress(app, key):
|
||||
#decidedly unused for now, i prefer mouse-only. ill keep the definition here in case i need debug tools.
|
||||
|
||||
# DEBUG
|
||||
if not app.debug: return
|
||||
if key == "m":
|
||||
app.save["cash"] = 1000000
|
||||
if key == "escape":
|
||||
os._exit(0) #suggested by AI, instantly exits without hanging like sys.exit(0)
|
||||
if key == "r":
|
||||
#reset save
|
||||
app.save = loadSave("thisisntarealsavefile.stupid")
|
||||
|
||||
#added by AI, but simply allows me to trigger a breakpoint manually to check state of app and variables
|
||||
#after some debate, this was the best option over something more complex
|
||||
@@ -412,9 +442,11 @@ def buyUpgrade(app, upgradeId):
|
||||
# extra attempts, etc.) and are read back in startSkillCheck.
|
||||
upgrade = [u for u in AVAILABLE_UPGRADES if u[0] == upgradeId][0] #find the specified upgrade
|
||||
name, category, value, price = upgrade
|
||||
print("attempting buy",upgrade)
|
||||
|
||||
if name in app.save["owned_upgrades"]: return False
|
||||
if price > app.save["cash"]: return False
|
||||
print("success!")
|
||||
|
||||
app.save["owned_upgrades"].append(name)
|
||||
app.save["cash"] -= price
|
||||
@@ -428,10 +460,12 @@ def buyBaitLicense(app, baitId):
|
||||
# setActiveBait). Bait determines which creatures are reachable in
|
||||
# pickRandomCreature. Deduct money, record ownership, persist.
|
||||
bait = [b for b in AVAILABLE_BAITS if b[0] == baitId][0] #find the specified upgrade
|
||||
name, max_difficulty, price = bait
|
||||
name, max_difficulty, price, img_file = bait
|
||||
|
||||
print("attempting buy",bait)
|
||||
if name in app.save["owned_baits"]: return False
|
||||
if price > app.save["cash"]: return False
|
||||
print("success!")
|
||||
|
||||
app.save["owned_baits"].append(name)
|
||||
app.save["cash"] -= price
|
||||
@@ -476,8 +510,8 @@ def redrawAll(app):
|
||||
if app.scene == "result":
|
||||
drawCatchDisplay(app)
|
||||
|
||||
|
||||
drawDebug(app)
|
||||
if app.debug:
|
||||
drawDebug(app)
|
||||
|
||||
#my self-hosted gitea repo also stores the image files, very convienient
|
||||
BASE_IMAGE_URL = "https://gitea.lockeshor.com/lockeshor/15112-fishing-miniproject/raw/branch/main/sprites/"
|
||||
@@ -560,6 +594,20 @@ def drawShopEntities(app):
|
||||
drawRect(right-8-40, top + 10, 40, bottom-top-20, fill="gold")
|
||||
drawLabel("$" + str(price), right - 10, centerY, align="right", size = 10)
|
||||
|
||||
#draw bait purchases
|
||||
for name, sceneFilter, left, right, top, bottom in [interactable for interactable in app.INTERACTABLES if interactable[0].startswith("bait-buy:")]:
|
||||
displayName = name.split(":")[1]
|
||||
|
||||
drawRect(left, top, right - left, bottom - top, fill=('gray' if displayName in app.save["owned_baits"] else 'rosyBrown'), border='bisque',borderWidth=4)
|
||||
|
||||
drawLabel(displayName, left + (right-left) / 2, bottom - 20, align="center")
|
||||
|
||||
img_file = [b for b in AVAILABLE_BAITS if b[0] == displayName][0][3]
|
||||
|
||||
|
||||
#Image creds: ALL ICONS FROM https://www.flaticon.com
|
||||
drawImage(BASE_IMAGE_URL + "bait-icons/" + img_file, left + (right-left) / 2, top + (bottom-top) / 2 - 10, width=80,height=80,align="center")
|
||||
|
||||
def drawSkillCheck(app):
|
||||
# Draw the active skill-check overlay: the circle, the target bars placed
|
||||
# around it (count/length from difficulty), and the rotating cursor at its
|
||||
@@ -599,16 +647,31 @@ def drawCatchDisplay(app):
|
||||
|
||||
|
||||
#star of surprise (turns out I cant make a star with assymetric height/width, so ill have to use an image)
|
||||
drawImage(BASE_IMAGE_URL + "surprise.png", app.width // 2, app.height // 2)
|
||||
#Image cred: https://pngtree.com/free-png-vectors/comics-bubbles
|
||||
drawImage(BASE_IMAGE_URL + "surprise.png", app.width // 2, app.height // 2 - 40, align = "center",width = 530, height = 530)
|
||||
|
||||
|
||||
#draw label
|
||||
if app.hookedFish != None:
|
||||
drawLabel(f"You Caught A {app.hookedFish["name"]}!",app.width // 2,210,align="center",size=18)
|
||||
drawLabel(app.hookedFish["description"],app.width // 2,230,align="center",size=12)
|
||||
#money bonus
|
||||
drawRect(460, 180, 120, 45, align = "center", rotateAngle = -25, fill='mediumSpringGreen', border="black")
|
||||
drawLabel(f"+ ${app.hookedFish["price"]}",460, 180, size=24, align = "center", rotateAngle = -25, fill='black')
|
||||
|
||||
#length and weight
|
||||
drawLabel(f"{app.hookedFish["length"]} in.",app.width // 2 - 40,260,align="center",size=14)
|
||||
drawLabel(f"{app.hookedFish["weight"]} lbs.",app.width // 2 + 40,260,align="center",size=14)
|
||||
|
||||
|
||||
#draw creature/error
|
||||
imgWidth = 300
|
||||
imgWidth = 200
|
||||
if app.hookedFish != None:
|
||||
trueimgW, trueimgH = getImageSize(BASE_IMAGE_URL + f"fish/{app.hookedFish["sprite-file"]}")
|
||||
imgHeight = imgWidth * (trueimgH / trueimgW)
|
||||
drawImage(BASE_IMAGE_URL + f"fish/{app.hookedFish["sprite-file"]}",
|
||||
app.width // 2,
|
||||
app.height // 2 - 50,
|
||||
app.height // 2 - 75,
|
||||
align = "center",
|
||||
width=imgWidth,
|
||||
height=imgHeight,
|
||||
@@ -619,7 +682,7 @@ def drawCatchDisplay(app):
|
||||
imgHeight = imgWidth * (trueimgH / trueimgW)
|
||||
drawImage(BASE_IMAGE_URL + "fail.png",
|
||||
app.width // 2,
|
||||
app.height // 2 - 50,
|
||||
app.height // 2,
|
||||
align = "center",
|
||||
width=imgWidth,
|
||||
height=imgHeight,
|
||||
@@ -631,6 +694,8 @@ def drawHud(app):
|
||||
# Draw the persistent heads-up display: current money, equipped bait, and
|
||||
# any brief status/instruction text ("click to cast", etc.). Overlaid on
|
||||
# every scene so the player always sees their core stats.
|
||||
|
||||
#I dont really need this unless I decide to add alert/tutorial messages
|
||||
pass
|
||||
|
||||
def drawDebug(app):
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"cash": 863268.0, "owned_baits": ["Worms"], "owned_upgrades": ["Spectral Rod", "Galaxy Rod"], "current_bait": "Worms", "catch_log": []}
|
||||
{"cash": 810706.0, "owned_baits": ["Worms", "Prawns", "Tuna", "Bass"], "owned_upgrades": ["Spectral Rod", "Galaxy Rod", "Glowing Rod", "Massive Bobber", "Huge Bobber", "Large Bobber", "Medium Bobber"], "current_bait": "Worms", "catch_log": []}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
Reference in New Issue
Block a user