Skip to content

Instantly share code, notes, and snippets.

@increpare
Created March 23, 2025 17:49
Show Gist options
  • Save increpare/4a7c6cea5dd4f9a436396a68e8205815 to your computer and use it in GitHub Desktop.
Save increpare/4a7c6cea5dd4f9a436396a68e8205815 to your computer and use it in GitHub Desktop.
susdfd (PuzzleScript Script)
Play this game by pasting the script in http://www.puzzlescript.net/editor.html
title susdfd
author David Skinner
homepage www.puzzlescript.net
verbose_logging
debug
========
OBJECTS
========
Background
lightgreen green
11111
01111
11101
11111
10111
Target
darkblue
.....
.000.
.0.0.
.000.
.....
Wall
brown darkbrown
00010
11111
01000
11111
00010
Player
black orange white blue
.000.
.111.
22222
.333.
.3.3.
l4a
brown
l4b
brown
l4c
brown
l5a
brown
l5b
brown
l5c
brown
crate
red
crate2
red
target2
blue
=======
LEGEND
=======
. = Background
# = Wall
P = Player
player_alt=player
O = Target
wall_or_crate = wall or crate
crate_or_target = crate or Target
l4a_or_l5a = l4a or l5a
l4a_or_l4b = l4a or l4b
l4a_or_l4b_alt = l4a or l4b
l4c_and_15c = l4c and l5a
player_or_wall = player or wall
crate_or_crate2 = crate or crate2
player_or_crate = player or crate
player_or_target = player or Target
crate2_or_Target2 = crate2 or target2
player_and_target = player and target2
crate_and_target = crate and Target
=======
SOUNDS
=======
================
COLLISIONLAYERS
================
Background
Target, target2
Player, wall, crate, crate2
l4a,l4b,l4c
l5a,l5b,l5c
======
RULES
======
[ l4a ] -> [ l4a no l4a_or_l4b ]
[ l4a ] -> [ l4a no l4a_or_l5a ]
[ l4a_or_l4b ] -> [ l4a_or_l4b no l4a ]
( TYPES OF ENTITY
object, single_layer_property, multi_layer_property, aggregates
object no object
object no single_layer_property
object no multi_layer_properly
single_layer_property no object
single_layer_property no single_layer_property
single_layer_property no multi_layer_property
multi_layer_property no object
multi_layer_property no single_layer_property
multi_layer_property no multi_layer_property
aggregates no object
aggregates no single_layer_property
aggreagtes no multi_layer_property
)
(object no object)
(no overlap)
[ player no crate ] -> cancel (handled correctly)
(overlap)
[ player_alt no player] -> cancel (nothing amiss detected - need to be better at handling synonyms I think!)
(object no single_layer_property)
(no overlap)
[ player no wall_or_crate ] -> cancel (handled correctly)
(overlap)
[ wall no wall_or_crate ] -> cancel (handled correctly)
(object no multi_layer_properly)
(no overlap)
[ player no crate_or_target ] -> cancel (could output warning that property could be simplifed)
(overlap)
[ crate no crate_or_target ] -> cancel (this rule vanishes without a trace...)
(single_layer_property no object)
(no overlap)
[ wall_or_crate no player ] -> cancel
(overlap)
[ wall_or_crate no crate ] -> cancel
(single_layer_property no single_layer_property)
(no overlap)
[ player_or_wall no wall_or_crate ] -> cancel
(overlap)
[ player_or_wall no wall_or_crate ] -> cancel
(single_layer_property no multi_layer_property)
(no overlap)
[ player_or_wall no crate_or_target ] -> cancel
(overlap)
[ player_or_crate no crate_or_target ] -> cancel
(multi_layer_property no object)
(no overlap)
[ crate_or_target no player ] -> cancel
(overlap)
[ crate_or_target no target ] -> cancel
(multi_layer_property no single_layer_property)
(no overlap)
[ crate_or_target no player_or_wall ] -> cancel
(overlap)
[ player_or_target no player_or_crate ] -> cancel
(multi_layer_property no multi_layer_property)
(no overlap)
[ crate_or_target no crate2_or_target2 ] -> cancel (no warning)
(overlap)
[ player_or_target no player_or_crate ] -> cancel (could warn about simplification possibility)
(aggregates no object)
(no overlap)
[ player_and_target no wall ] -> cancel
(overlap)
[ player_and_target no target ] -> cancel
(aggregates no single_layer_property)
(no overlap)
[ player_and_target no wall_or_crate ] -> cancel
(overlap)
[ player_and_target no player_or_crate ] -> cancel
(aggreagtes no multi_layer_property)
(no overlap)
[ player_and_target no crate2_or_target2 ] -> cancel
(overlap)
[ player_and_target no crate_or_target ] -> cancel
( The above is not exhaustive though! The general structure, because of the fundamental simplicity of 'no' statements is
[ <list of properties...> NO property ]
what I want to say, fundamentally is "you don't need to say 'no property', because you've already specified contents for all the property's layers.
No, this isn't right. There are cases like.
The simplest approach is to just ignore properties on the left - just have a strict
occupancy mask.
The next approach, which is nice, is to also allow single_layer_properties, but that's where the complexity begins:
)
[ player_or_crate no wall ] -> cancel (this is easy - no object overlap!)
[ player_or_crate no crate ] -> cancel (uh, possible simplification, but maybe not worth annoying the user about it)
[ player_or_crate no crate_or_target ] -> cancel (ditto)
(what algorithm takes into account both simple object and single_layer_properties?
1: calculate occupancy at entity and layer level for all objects, synonyms, aggregates, and single_layer_properties
2: for each'no' entity :
3a: check if is (object or property) is 'covered' by the layer mask, and doesn't intersect with the object mask.
3b: if so, can cull the 'no' bit.
IS IT BETTER TO PRECALCULATE THE NO MASK AND CHECK AGAINST INDIVIDUAL OBJECTS ON THE LEFT? (maybe this works far more generally! or maybe i need to do a second pass at the end with info about the 'no' object mask , going throuhg the 'yes' properties?)
this algorithm doesn't cover cases like
)
[ player_or_target no player_or_crate ] -> cancel
(could be simplified to "[ target no crate ] -> cancel" - which the compiler does, so you know fine. )
(the following isn't getting caught...)
[ l4a_or_l4b_alt ] -> [ l4a_or_l4b_alt no l4a_or_l4b ]
[ l4a_or_l4b ] -> [ l4a_or_l4b no l4a_or_l5a ]
[ no l4a_or_l4b ] -> [ no l4a_or_l4b l4a ]
(WHEN CAN I REMOVE A NO X)
(CASE 1: OBJECT / NO OBJECT
l1_objectA no l1_objectB, where they are different objects
)
[ player no wall ] -> cancel
[ no l4a l4b ] -> cancel
(CASE 2: SINGLE_LAYER_PROPERTY / NO OBJECT
l1_single-layer-property no l1_object, where object doesn't overlap with property
)
[ l4a_or_l4b no l4c ] -> cancel
(CASE 3: MULTI_LAYER_PROPERTY / NO OBJECTS
IF NEGATIVE *OBJECT* MASK COVERS MULTI_LAYER_PROPERTY, IT'S GONE
)
[ l4a_or_l5a no l4a no l5a ] -> cancel
(CASE 4: OBJECT / NO SINGLE_LAYER_PROPERTY
OBJECT NOT IN PROPERTY
)
[ l4c no l4a_or_l4b ] -> cancel
(CASE 4: MULTI_LAYER_OCCUPANCY / NO SINGLE_LAYER_PROPERTY
OBJECT IN PROPERTY
)
[ l4a no l4a_or_l4b ] -> cancel
(CASE 5: MULTI_OCCUPANCY / NO MULTI_LAYER_OCCUPANCY)
[ l4c l5c no l4a_or_l5a ] -> cancel
(in general, in "X no Y", layer occupation is a big factor. If
X occupies all the same layers as Y, you'd think Y would be surperfluous.
However, if X overlaps with Y on a per-object level, it gets complicated.)
(So, what's my algorithm going to be?
X no Y (best usability wise, mid optimization wise, to do for each Y as written in code)
1: get layer occupancies, L(X) and L(Y),
2: If L(Y) is contained in L(X) calculate object-level occupancies.
3a: If O(X) and O(Y) disjoint, you can cull the 'no' statement, give warning.
3b: If O(X) overlaps with O(Y), in principle can subtract X from Y, and regenerate the negative statement. Dont give a warning.
)
[ no l4a_or_l4b l4c ] -> cancel
[ no l4a_or_l5a l4c ] -> cancel
[ no l4a_or_l5a l4a ] -> cancel
[ no l4a_or_l5a l4b l5b ] -> cancel
[ no l4a_or_l4b l5a ] -> cancel
(this technically should also vanish, perhaps harder to detect though)
( [ no l4a_or_l4b 14c_and_15c ] -> cancel )
(RHS OVERLAP TEST)
[ l4a ] -> [ l4a l5a no l4a_or_l5a ]
(WHEN DELETING STUFF FROM THE LHS, SHOULD DELETE FROM THE RHS AS WELL IF IT'S THE SAME, RIGHT? this is true for 'nos' in general though...)
==============
WINCONDITIONS
==============
=======
LEVELS
=======
####..
#.O#..
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment