Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pab's Gothic Lock Breaker

A solver for the Gothic 1 Remake lockpicking minigame, plus optional playback that types the solution into the game for you.

The solver treats the puzzle as a shortest-path problem on an unweighted graph and uses breadth-first search, so the sequence it returns is provably the minimum number of moves for that lock.


The puzzle

A lock has N plates (usually 4 to 7, we denote the plates alphabetically - a, b, c, ...). Each plate sits at one of 7 positions, numbered 1 ( the plate is fully right, hence the pin is in the left most hole) … 7 (the plate is fully left, hence the pin is in the right most hole). You win when every plate is at position 4 (middle position).

The catch: plates are coupled. Moving one plate also moves others, according to rules specific to each lock — e.g. "moving plate a right also moves c and d right, and b left". The coupling is mirrored: if moving a right pushes b left, then moving a left pushes b right. That's why only one direction per plate has to be described.

In-game controls

Key Action
w move cursor down the plate list (a → b → c → …)
s move cursor up the plate list (… → c → b → a)
a move the selected plate left (position +1)
d move the selected plate right (position −1)

The cursor always starts on plate a when a lock opens. There is no wrap-around at the ends of the list.


Install

Requires uv. From the repo root:

uv sync

That creates .venv/ and installs pydirectinput (sending keys the game will actually read) and keyboard (the global start/abort hotkey).


Configuring a lock

Open lock_breaker.py and edit two module-level values.

start — the plate positions currently on screen, left to right:

start = (2, 3, 5, 7, 6, 1)

plate_couplings — one vector per plate, each describing what happens when you move that plate right. Entry i of a vector is the effect on plate i:

plate_couplings = [
    (1, 1, 1, 1, 0, 0),    # moving plate a right: a, b, c, d all move right
    (-1, 1, -1, 0, 0, 0),  # moving plate b right: b right; a and c move left
    (0, 0, 1, 0, 0, 0),    # moving plate c right: only c moves
    ...
]

You only describe the "right" direction — the solver derives "left" by negating each vector. plate_couplings must have one vector per plate, and every vector must be the same length as start.

A mistyped vector is the most common failure. It produces a plausible-looking solution that simply doesn't work in-game. Double-check the couplings against the screen before running.


Running

Solve only — prints the move list:

uv run lock_breaker.py

Output is the minimal sequence of plate moves:

['c-left', 'c-left', 'e-right', 'a-left', ...]

Solve and play it into the game:

uv run lock_player.py
  1. It prints the solution and waits.
  2. Alt-tab into Gothic. Make sure the lockpicking screen is focused and the cursor is on plate a.
  3. Press F8 to play the sequence.
  4. Press ESC at any time to abort.

Playback tunables live at the top of lock_player.py: HOTKEY, ABORT_KEY, KEY_DELAY, KEY_HOLD, COUNTDOWN.


Notes

  • On Windows the keyboard library's global hotkey may need the terminal to run as administrator to register while the game has focus.
  • Move counts can be large — 68 moves has been observed for a lock with awkward coupling. That is genuinely the minimum for that lock, not a bug; BFS proves no shorter sequence exists.
  • Playback uses pydirectinput rather than pyautogui or keyboard, because games read DirectInput/raw input and typically ignore window-message-based synthetic input.

About

Simple set of scripts to unlock any lock in the Gothic Remake game.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages