Last active
June 4, 2025 22:34
-
-
Save inclement/458ac36579dda092d8760585f08da80c to your computer and use it in GitHub Desktop.
History of the Velsokomagnet (PuzzleScript Script)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Play this game by pasting the script in http://www.puzzlescript.net/editor.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| title History of the Velsokomagnet | |
| author inclement | |
| homepage https://inclem.net/ | |
| require_player_movement | |
| key_repeat_interval 0.1 | |
| again_interval 0.04 | |
| run_rules_on_level_start | |
| ======== | |
| OBJECTS | |
| ======== | |
| Nothing | |
| black | |
| Background | |
| #eeeeee #eeeeee | |
| 01000 | |
| 01000 | |
| 10011 | |
| 00100 | |
| 01000 | |
| Target | |
| #c9c9c9 #eeeeee green | |
| 01010 | |
| 10001 | |
| 00200 | |
| 10001 | |
| 01010 | |
| PlayerTarget | |
| #c9c9c9 darkgreen green | |
| .0.0. | |
| 00000 | |
| .020. | |
| 00000 | |
| .0.0. | |
| Wall | |
| #a59aa5 #bb77bb | |
| 00000 | |
| 00000 | |
| 00000 | |
| 00000 | |
| 00000 | |
| WallBase | |
| #a59aa5 #bb77bb #aa9daa | |
| 00000 | |
| 00000 | |
| 00000 | |
| 00000 | |
| 11111 | |
| Player | |
| #0055ee #0044dd | |
| .0.0. | |
| 01110 | |
| .101. | |
| 01110 | |
| .0.0. | |
| Crate | |
| #ee8822 #dd7711 | |
| 0.0.0 | |
| .111. | |
| 00000 | |
| .111. | |
| 0.0.0 | |
| PlayerCrateRightMarker | |
| #ee8822 | |
| ....0 | |
| ..... | |
| ....0 | |
| ..... | |
| ....0 | |
| PlayerCrateAboveMarker | |
| #ee8822 | |
| 0.0.0 | |
| ..... | |
| ..... | |
| ..... | |
| ..... | |
| PlayerCrateLeftMarker | |
| #ee8822 | |
| 0.... | |
| ..... | |
| 0.... | |
| ..... | |
| 0.... | |
| PlayerCrateBelowMarker | |
| #ee8822 | |
| ..... | |
| ..... | |
| ..... | |
| ..... | |
| 0.0.0 | |
| CratePlayerRightMarker | |
| #0055ee | |
| ..... | |
| ....0 | |
| ..... | |
| ....0 | |
| ..... | |
| CratePlayerAboveMarker | |
| #0055ee | |
| .0.0. | |
| ..... | |
| ..... | |
| ..... | |
| ..... | |
| CratePlayerLeftMarker | |
| #0055ee | |
| ..... | |
| 0.... | |
| ..... | |
| 0.... | |
| ..... | |
| CratePlayerBelowMarker | |
| #0055ee | |
| ..... | |
| ..... | |
| ..... | |
| ..... | |
| .0.0. | |
| MovedCrateMarker | |
| pink | |
| 00000 | |
| 0...0 | |
| 0...0 | |
| 0...0 | |
| 00000 | |
| CrateOnTargetMarker | |
| lightgreen | |
| ..... | |
| ..... | |
| ..0.. | |
| ..... | |
| ..... | |
| PlayerOnTargetMarker | |
| lightgreen | |
| ..... | |
| ..... | |
| ..0.. | |
| ..... | |
| ..... | |
| MovedPlayerMarker | |
| red | |
| JustMovedPlayerMarker | |
| transparent | |
| IntroCrate | |
| #ee8822 #dd7711 | |
| .000. | |
| 01110 | |
| 00000 | |
| 01110 | |
| .000. | |
| IntroCrateTarget | |
| #c9c9c9 #eeeeee green | |
| 10001 | |
| 00000 | |
| 00200 | |
| 00000 | |
| 10001 | |
| IntroPlayerTarget | |
| #c9c9c9 #eeeeee green | |
| 11111 | |
| 11111 | |
| 11211 | |
| 11111 | |
| 11111 | |
| IntroPlayerVisualMask | |
| #0055ee #0044dd | |
| 00.00 | |
| 0...0 | |
| ..... | |
| 0...0 | |
| 00.00 | |
| IntroPlayerTargetVisualMask | |
| #c9c9c9 | |
| 00.00 | |
| 0...0 | |
| ..... | |
| 0...0 | |
| 00.00 | |
| VerticalForceMarker | |
| #aaaaff | |
| ..0.. | |
| ..0.. | |
| ..0.. | |
| ..0.. | |
| ..0.. | |
| HorizontalForceMarker | |
| #aaaaff | |
| ..... | |
| ..... | |
| 00000 | |
| ..... | |
| ..... | |
| ======= | |
| LEGEND | |
| ======= | |
| . = Background | |
| # = Wall | |
| P = Player | |
| * = Crate | |
| @ = Crate and Target | |
| O = Target | |
| x = PlayerTarget | |
| q = Player and PlayerTarget | |
| z = Crate and PlayerTarget | |
| N = Nothing | |
| i = IntroCrate | |
| j = IntroCrateTarget | |
| ======= | |
| SOUNDS | |
| ======= | |
| ================ | |
| COLLISIONLAYERS | |
| ================ | |
| Background | |
| Nothing | |
| Target, PlayerTarget, IntroCrateTarget, IntroPlayerTarget | |
| IntroPlayerTargetVisualMask | |
| PlayerCrateRightMarker | |
| PlayerCrateLeftMarker | |
| PlayerCrateAboveMarker | |
| PlayerCrateBelowMarker | |
| CratePlayerRightMarker | |
| CratePlayerAboveMarker | |
| CratePlayerLeftMarker | |
| CratePlayerBelowMarker | |
| (Note these are the only actual physics objects for which we care about collision, | |
| everything else is for game logic or prettiness) | |
| Player, Wall, Crate, IntroCrate | |
| WallBase ( Note WallBase drawn on top of Wall as it's just decoration ) | |
| MovedPlayerMarker | |
| MovedCrateMarker | |
| JustMovedPlayerMarker | |
| IntroPlayerVisualMask | |
| CrateOnTargetMarker, PlayerOnTargetMarker | |
| HorizontalForceMarker | |
| VerticalForceMarker | |
| ====== | |
| RULES | |
| ====== | |
| ( Normal sokoban rules for the introductory level only. ) | |
| [ > Player | IntroCrate ] -> [ > Player | > IntroCrate ] | |
| late [IntroCrate IntroCrateTarget no CrateOnTargetMarker] -> [IntroCrate IntroCrateTarget CrateOnTargetMarker ] | |
| late [IntroCrate IntroCrateTarget no CrateOnTargetMarker] -> [IntroCrate IntroCrateTarget CrateOnTargetMarker ] | |
| late [Player no IntroPlayerVisualMask] [IntroCrateTarget] -> [Player IntroPlayerVisualMask] [IntroCrateTarget] | |
| late [IntroPlayerVisualMask no Player] -> [ ] | |
| late [PlayerTarget no IntroPlayerTargetVisualMask] [IntroCrateTarget] -> [PlayerTarget IntroPlayerTargetVisualMask] [IntroCrateTarget] | |
| ( Velsokomagnet rules for other levels:) | |
| (The player pushes crates when moving directly into them. Pushed crates | |
| are marked with a MovedCrateMarker because we want to distinguish | |
| crates the player directly pushed this way from those pushed from afar.) | |
| [ > Player | Crate ] -> [ > Player | > Crate > MovedCrateMarker ] | |
| [ ^ Player | Crate ] -> [ ^ Player | ^ Crate ^ MovedCrateMarker ] | |
| [ < Player | Crate ] -> [ < Player | < Crate < MovedCrateMarker ] | |
| [ v Player | Crate ] -> [ v Player | v Crate v MovedCrateMarker ] | |
| (Crates can push other crates, but if the player is trying to directly | |
| push a crate into a blockage then cancel the move. Note we can't just | |
| rely on the collision layer logic because we're adding in rigid-body | |
| logic for a Player that is velcroed to any crates; without these rules | |
| the Player could move along the side of several adjacent crates against | |
| a blockage) | |
| [ > Crate | Crate ] -> [ > Crate | > Crate ] | |
| (The following works because we only have up to 4 crates in a level. | |
| This could be done in a maybe-better way using more objects carrying | |
| collision logic, but doesn't seem worth worrying about given this is | |
| simple enough.) | |
| [ > MovedCrateMarker | Crate | Crate | Crate | Crate | Wall ] -> cancel | |
| [ > MovedCrateMarker | Crate | Crate | Crate | Wall ] -> cancel | |
| [ > MovedCrateMarker | Crate | Crate | Wall ] -> cancel | |
| [ > MovedCrateMarker | Crate | Wall ] -> cancel | |
| [ > MovedCrateMarker | Wall ] -> cancel | |
| (We could run the repulsion logic in a single pass, but we use "again" | |
| so that we can have a brief marker when the repulsion has been applied. | |
| This hopefully reminds the player of the effect.) | |
| [ > Player | ] -> [ > Player | JustMovedPlayerMarker ] again | |
| (The Player will only be on top of a JustMovedPlayerMarker in the "again" | |
| pass. These rules apply repulsion in that pass.) | |
| [ Player JustMovedPlayerMarker | Crate ] -> [Player JustMovedPlayerMarker | Crate MovedCrateMarker ] | |
| [ Player JustMovedPlayerMarker | ... | Crate no MovedCrateMarker ] -> [ Player JustMovedPlayerMarker | ... | > Crate ] | |
| [Player JustMovedPlayerMarker] -> [Player] | |
| (If any JustMovedPlayerMarker is present then we're in the first pass, so | |
| draw repulsion lines to mark the logic being applied.) | |
| horizontal [Crate no MovedCrateMarker |...| no HorizontalForceMarker |...| JustMovedPlayerMarker] -> [Crate |...| HorizontalForceMarker | ... | JustMovedPlayerMarker] | |
| vertical [Crate no MovedCrateMarker| ... |no VerticalForceMarker|...| JustMovedPlayerMarker] -> [Crate |...| VerticalForceMarker | ... | JustMovedPlayerMarker] | |
| (If we're drawing any nice markers for being velcroed, move these with the player.) | |
| [> Player PlayerCrateRightMarker ] -> [> Player > PlayerCrateRightMarker ] | |
| [> Player PlayerCrateLeftMarker ] -> [> Player > PlayerCrateLeftMarker ] | |
| [> Player PlayerCrateAboveMarker ] -> [> Player > PlayerCrateAboveMarker ] | |
| [> Player PlayerCrateBelowMarker ] -> [> Player > PlayerCrateBelowMarker ] | |
| [> Crate CratePlayerRightMarker ] -> [> Crate > CratePlayerRightMarker ] | |
| [> Crate CratePlayerLeftMarker ] -> [> Crate > CratePlayerLeftMarker ] | |
| [> Crate CratePlayerAboveMarker ] -> [> Crate > CratePlayerAboveMarker ] | |
| [> Crate CratePlayerBelowMarker ] -> [> Crate > CratePlayerBelowMarker ] | |
| (If we have finished in the "again" pass, we can now remove the force markers. | |
| Note because this is a "late" rule the player will have moved on top of | |
| the marker on the first pass through.) | |
| late [Player no JustMovedPlayerMarker] [HorizontalForceMarker] -> [Player] [] | |
| late [Player no JustMovedPlayerMarker] [VerticalForceMarker] -> [Player] [] | |
| (Clear up logic helper markers) | |
| late [ MovedCrateMarker ] -> [ ] | |
| (Draw an indicator when crates or the player are on their respective targets ) | |
| late [Player PlayerTarget no PlayerOnTargetMarker] -> [Player PlayerTarget PlayerOnTargetMarker] | |
| late [PlayerOnTargetMarker no Player] -> [ ] | |
| late [Crate Target no CrateOnTargetMarker] -> [Crate Target CrateOnTargetMarker] | |
| late [CrateOnTargetMarker no Crate no IntroCrate] -> [ ] | |
| (Draw cosmetic markers on some walls for visual variety) | |
| late DOWN [ Wall | no Wall ] -> [WallBase Wall | ] | |
| late Down [ WallBase | Wall ] -> [ | Wall ] | |
| (If we're next to a crate but haven't yet drawn a cosmetic marker, | |
| do that now) | |
| late RIGHT [ Player no PlayerCrateRightMarker | Crate ] -> [ Player PlayerCrateRightMarker | Crate CratePlayerLeftMarker] | |
| late UP [ Player no PlayerCrateAboveMarker | Crate ] -> [ Player PlayerCrateAboveMarker | Crate CratePlayerBelowMarker] | |
| late LEFT [ Player no PlayerCrateLeftMarker | Crate ] -> [ Player PlayerCrateLeftMarker | Crate CratePlayerRightMarker ] | |
| late DOWN [ Player no PlayerCrateBelowMarker | Crate ] -> [ Player PlayerCrateBelowMarker | Crate CratePlayerAboveMarker ] | |
| ============== | |
| WINCONDITIONS | |
| ============== | |
| (Note these are specified so as to work also in the intro level that has no Crates) | |
| all Target on Crate | |
| all Player on PlayerTarget | |
| all IntroCrateTarget on IntroCrate | |
| (Make sure win conditions only trigger at the end of the "again" pass) | |
| no JustMovedPlayerMarker | |
| ======= | |
| LEVELS | |
| ======= | |
| (Normal sokoban introduction) | |
| message (1 / 12) The original sokoban was invented when a global surplus of crates and targets necessitated a new form of warehouse management. PUSH the free crate to its target location. | |
| nnnnn#####nnn | |
| nnnnn#iii#nnn | |
| ######i..#nnn | |
| ####i....#nnn | |
| #i.....#.#nnn | |
| #ip.#i.#.###n | |
| #i.....#.i##n | |
| ########.i##n | |
| nnnn#.....i#n | |
| nnnn#.j...x#n | |
| nnnn#iii.###n | |
| nnnn########n | |
| message (2 / 12) Later advances in materials science introduced the sokomagnetic force that repelled the crates... | |
| message (2 / 12) ...also the warehouse contents were covered in velcro for storage convenience, after an unfortunate incident involving the lead engineer's car keys. | |
| message (2 / 12) The player now REPELS all crates with the same row or column...unless they're adjacent in which case it STICKS to them forever. Press "R" to restart if necessary. | |
| (Basic introduction) | |
| nnnnn#####nnn | |
| nnnnn#...#nnn | |
| ######...#nnn | |
| ####.....#nnn | |
| #......#.#nnn | |
| #.p.#*.#.###n | |
| #......#..##n | |
| ########..##n | |
| nnnn#......#n | |
| nnnn#.o...x#n | |
| nnnn#....###n | |
| nnnn########n | |
| message (3 / 12) The resulting entity became known as...the VELSOKOMAGNET. | |
| (Easy 3) | |
| ########### | |
| #.........# | |
| #.........# | |
| #..*......# | |
| #...o...x.# | |
| #....o....# | |
| #.....*.#.# | |
| #.........# | |
| #..p......# | |
| ########### | |
| message (4 / 12) The velsokomagnet quickly became popular. Crate manipulation was easier than ever! | |
| (Easy 2) | |
| ########## | |
| #........# | |
| #..#.....# | |
| #..z..o..# | |
| #.....#..# | |
| #..*.....# | |
| #..#.....# | |
| #p.......# | |
| ###.o.#### | |
| ###...#### | |
| ########## | |
| message (5 / 12) Using the velcro was considered quite gauche, but was not unknown. | |
| (Velcro easy introduction) | |
| nnnn#####nn | |
| nnnn#...#nn | |
| #####.#.#nn | |
| ###.#.#.#nn | |
| ##.o.*..#nn | |
| #.ox#.#.### | |
| ##.......## | |
| #.p###.#.## | |
| #.#..*....# | |
| #.........# | |
| ######.#..# | |
| nnnnn#...## | |
| nnnnn###### | |
| message (6 / 12) Still, the most high-profile designers generally felt the sokomagnetic interaction was more stimulating to the intellect. | |
| (Easy 1) | |
| ########## | |
| #p.....### | |
| #........# | |
| #.#*.#...# | |
| #x#.O.#..# | |
| #....*...# | |
| #..#.#...# | |
| #.O....#.# | |
| ########## | |
| message (7 / 12) Attitudes steadily changed until the velcro was often a key part of the solution. | |
| (Velcro easy 2) | |
| nnn###########nnn | |
| nnn####...####nnn | |
| nnn#.........#nnn | |
| ####.........#### | |
| #..o....***...o.# | |
| ####.......p.#### | |
| nnn#....o....#nnn | |
| nnn#####x#####nnn | |
| nnn###########nnn | |
| message (8 / 12) During its heights, the velsokomagnet's popularity eclipsed more traditional warehouse variants. | |
| (Velcro easy 1) | |
| nnnnn#######n | |
| nnnnn#.....#n | |
| nnnnn#.....#n | |
| #######..#.#n | |
| #.......*..#n | |
| #...##..#..#n | |
| #......###.## | |
| ####...###.o# | |
| nnn#...###.x# | |
| nnn#.*..##.## | |
| nnn#.....#.#n | |
| nnn#....p.o#n | |
| nnn####....#n | |
| nnnnnn###..#n | |
| nnnnnnnn####n | |
| message (9 / 12) For instance, the next warehouses are a duet of puzzles produced as part of Queen Elizabeth's Ruby Jubilee. | |
| (Easy 4) | |
| #########nnnnnn | |
| ##.....##nnnnnn | |
| ##.#...######## | |
| ##......#.....# | |
| ##..#*..#...x.# | |
| ##............# | |
| #.....*.......# | |
| #.......#.....# | |
| #.......#.opo.# | |
| #.......#.....# | |
| ############### | |
| message (10 / 12) The eventual downfall of the velsokomagnet was not due to disinterest, but economics. | |
| (Easy 5) | |
| #########nnnnnn | |
| ##.....##nnnnnn | |
| ##...#.##nnnnnn | |
| ##.#*..######## | |
| ##......#.....# | |
| ##..#*..#...x.# | |
| ##............# | |
| #.....*.......# | |
| #.......#...o.# | |
| #.......#.opo.# | |
| #.......#.....# | |
| ############### | |
| message (11 / 12) The materials used to create stable sokomagnetic monopoles became more valuable in other industries, making velsokomagnetic warehouses expensive to maintain. | |
| (Medium? 1) | |
| (I "fixed" an intended-logic break with the upper-left counter crate, but that's a bit | |
| rubbish as nobody likes counters :< ) | |
| nnnnnnn######nn | |
| ########...##nn | |
| #.o...*#.#.##nn | |
| ########.#..#nn | |
| nnn##o##..#.### | |
| nnn#o..x*#...## | |
| nnn###o#......# | |
| nnn###.#..*.#.# | |
| nnn#.......##.# | |
| nnn#...*..###.# | |
| nnn#..p..####.# | |
| nnn##...#####.# | |
| nnn############ | |
| message (12 / 12) In the end velsokomagnetic warehouses were financially unsustainable. Public interest moved on, and the velsokomagnet is now mostly confined to the annals of history. | |
| message (12 / 12) This last example was the winner of a public competition, demonstrated last year at the world warehouse design expo using one of the last remaining velsokomagnets. | |
| (Medium 1 - not fully tested for simpler solutions ) | |
| ########### | |
| #.....p...# | |
| #.o#..###.# | |
| #.........# | |
| #..#..#.#.# | |
| #...#..*..# | |
| ##.....#..# | |
| n#.#.*..#.# | |
| n#..#.....# | |
| n#..#*...x# | |
| n#..o....o# | |
| n#.o....#.# | |
| n#....###*# | |
| n########## | |
| message That concludes this history of the velsokomagnetic era in sokoban warehouse arrangement. Any questions? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment