WTS/game/scripts/minigames/puzzle.rpy
LoafyLemon 38d2494bc3 Fix conflicting properties (by Gouvernathor)
big work
what was reliable before is now not, in recent versions of renpy, which is why we added that new config (which I put in say.rpy, but it can be moved somewhere else)
Also fixes the game_menu's title position, incidentally

some changes are incompatible with my diary and achievement branches, respectively, they will need to be merged with a bit of manual care
2024-03-25 14:57:36 +00:00

163 lines
6.5 KiB
Plaintext

init python:
def generate_puzzle(grid, difficulty, blank):
tiles = grid*grid
difficulty = difficulty * tiles
puzzle = list(range(tiles))
renpy.random.shuffle(puzzle)
def is_valid():
inversions = 0
for x in range(tiles):
for y in range(x+1, tiles):
if not (puzzle[x] == blank or puzzle[y] == blank) and puzzle[x] > puzzle[y]:
inversions += 1
# If the grid width is odd, then every solvable state has an even number of inversions.
# If the grid width is even, then every solvable state has:
# an even number of inversions if the blank is on an odd numbered row counting from the bottom OR
# an odd number of inversions if the blank is on an even numbered row counting from the bottom
if (grid % 2 == 1):
is_solvable = (inversions % 2 == 0)
else:
blank_row = grid - (puzzle.index(blank) // grid)
is_solvable = (inversions % 2 != blank_row % 2)
too_difficult = (inversions <= difficulty)
return (is_solvable and not too_difficult)
while not is_valid():
renpy.random.shuffle(puzzle)
return puzzle
screen puzzle_minigame():
tag puzzle
zorder 30
default tries = 0
default tiles = generate_puzzle(grid=4, difficulty=game.difficulty, blank=15)
default hint = False
$ score = 0
add "gui_fade"
use close_button()
use meter(fill=100-tries)
frame:
align (0.5, 0.5)
background Transform("interface/puzzle/background.webp", align=(0.5, 0.5))
grid 4 4:
for i, tile in enumerate(tiles):
$ img = "interface/puzzle/{}.webp".format(tile)
$ empty = tiles.index(15)
$ is_valid = (i in (empty-1, empty+1, empty-4, empty+4)
and not ( (empty % 4 == 3) and (i % 4 == 0) )
and not ( (empty % 4 == 0) and (i % 4 == 3) ) )
$ action = None
$ hover = None
if i is empty:
$ idle = Null()
elif not is_valid:
$ idle = img
else:
$ action = [SetScreenVariable("tries", tries+1), Function(list_swap_values, tiles, empty, i)]
$ idle = At(img, pulse_hover(pause=3.0, strength=0.075))
$ hover = image_hover(idle)
if i == tile:
$ score += 1
imagebutton:
xysize (94, 94)
idle idle
hover hover
action action
if hint:
button:
style "empty"
align (0.5, 0.5)
background Transform("interface/puzzle/background.webp", align=(0.5, 0.5))
add "interface/puzzle/puzzle.webp"
action NullAction()
if score >= 15:
timer 0.1 action Return(True)
vbox:
yanchor 0.0
ypos 0.85
xalign .5
textbutton "-Hint-" xalign 0.5 action ToggleScreenVariable("hint", True, False)
if tries >= 75:
textbutton "-Force it open-" xalign 0.5 action Return(False) at pulse_hover
if config.developer:
textbutton "-Solve it-" xalign 0.5 action SetScreenVariable("tiles", list(range(16)))
label puzzle_minigame:
call screen puzzle_minigame()
$ renpy.block_rollback()
if _return == True:
gen "Finally..." ("base", xpos="far_left", ypos="head")
gen "What is this?" ("base", xpos="far_left", ypos="head")
gen "Sweet, phoenix tears! Down the hatch we go." ("base", xpos="far_left", ypos="head")
play sound "sounds/pop03.ogg"
play sound2 "sounds/gulp.ogg"
pause 1
play sound "sounds/gulp.ogg"
gen "...." ("base", xpos="far_left", ypos="head")
gen "I feel no difference..." ("base", xpos="far_left", ypos="head")
$ achievements.unlock("puzzle")
elif _return == False:
gen "Fuck it..." ("angry", xpos="far_left", ypos="head")
play sound "sounds/door_down.ogg"
with hpunch
"{size=32}*Smash*{/size}"
play sound "sounds/glass_shatter.ogg"
gen "A broken bottle..." ("base", xpos="far_left", ypos="head")
gen "Oh well, too late now. Back to my usual--" ("base", xpos="far_left", ypos="head")
else: # Closed
gen "(Maybe next time...)" ("base", xpos="far_left", ypos="head")
jump main_room_menu
gen "Hold on a second, there's a book in here..." ("base", xpos="far_left", ypos="head")
gen "Seems to be some sort of notebook, I'll skim through it..." ("base", xpos="far_left", ypos="head")
call book_start
gen "\"My dear phoenix has been losing his feathers lately, I think it's time soon\"..." ("base", xpos="far_left", ypos="head")
gen "(Time for what?)" ("base", xpos="far_left", ypos="head")
gen "\"That Potter boy is mighty cute, looks just like his father\"..." ("base", xpos="far_left", ypos="head")
gen "(Well, well...)" ("grin", xpos="far_left", ypos="head")
gen "\"Severus gave me a weird look today, I wonder what he thinks about my\"..." ("base", xpos="far_left", ypos="head")
gen "(This is all trash...)" ("angry", xpos="far_left", ypos="head")
gen "(Wait a minute... this seems interesting.)" ("base", xpos="far_left", ypos="head")
gen "\"I was walking around in the seventh floor corridor looking for a bathroom\"..." ("base", xpos="far_left", ypos="head")
gen "\"Whilst searching, a room that I had never seen before appeared, filled with chamber pots... But when I returned later, it was gone\"." ("base", xpos="far_left", ypos="head")
call book_end
gen "(I've seen enough magic to know where this is going... I should investigate that corridor on the seventh floor.)" ("base", xpos="far_left", ypos="head")
call give_reward("You've unlocked something on the 7th floor, check your map to get there.","/images/rooms/room_of_requirement/mirror.webp")
if states.cardgame.unlocked:
gen "What's this?" ("base", xpos="far_left", ypos="head")
call give_reward("You have found a card at the bottom of the box!", "images/cardgame/t1/other/elf_v1.webp")
$ unlocked_cards += [card_item_elf]
$ states.map.seventh_floor.unlocked = True
$ puzzle_box_ITEM.owned = 0
$ puzzle_box_ITEM.used = True
$ chair_OBJ.hidden = False
if game.daytime:
jump night_start
else:
jump day_start