title Aperture Science Sokoban Testing Initiative
author Ed Turner, with additional level design by Kalev Tait
homepage www.thoughtcheckgames.com
again_interval 0.02
key_repeat_interval 0.2
background_color lightgray
text_color black
run_rules_on_level_start


========
OBJECTS
========

Background
Grey LightGrey
11111
11111
11111
11111
11111

Wall
Grey White
00000
01110
01110
01110
00000

Metal
darkgrey
00000
0.0.0
00.00
0.0.0
00000

Hole
Black

(Buttons open doors. Behind metal, they are laser-activated)
(Put a Lie behind a button and a door or rotating wall and they will be on a seperate circuit.)
Button
black Red lightgrey
22222
20002
20102
20002
22222

Door
Grey DarkGrey
11111
00100
00100
00100
11111

(In addition to being, well, an open door, OpenDoor marks metal which can be flipped to a wall surface when a button is pushed. Put a lie behind it to be on the second circuit.)
DoorOpen
lightgrey DarkGrey
10001
00000
00000
00000
10001

(Target is the exit point. It also shows the next portal color, when applicable. It ALSO provides a temporary storage space for shots when portalling. It is ALSO a temporary token for rotating walls when they are on the second circuit. No, really.)
Target
White DarkGray grey lightgrey
31113
12.21
1.0.1
12.21
31113




(WeighedButton is used to both behing crates to mark where buttons were and behind the exit to illustrate when the next portal is orange. Oh, and then it's an Inconvenient Science Pit)
WeighedButton
Red orange black
22022
20102
01010
20102
22022

(NextShotBlue, behind the target, illustrates that the next shot will be blue. By itself, it's a Meterial Emancipation Grid / fizzler. It's also used as a marker behind rotating walls when they have their wall side out.)

NextShotBlue
Blue lightblue
1.1.1
.101.
10101
.101.
1.1.1


(Crates and sentries can be pushed around. Crates can even push sentries!)
Crate
Black DarkGray LightGray
11.11
11011
.000.
11011
11.11


Sentry
White Blue Black lightgray
..0..
.010.
30003
.202.
2.2.2

(These are deadly lasers. They are on seperate layers, so they can even cross. There's no good reason they're three pixels, except that I like the dashed look more than the solid lines.)
LaserH
Red
.....
.....
.000.
.....
.....

LaserV
Red
.....
..0..
..0..
..0..
.....

(Chell kicks ass. She's the reason I did all this work, really.)

ChellD
Black LightBrown Orange White Blue
.000.
.111.
2032.
0402.
.2.2.

ChellU
Black LightBrown Orange White Blue
.000.
.101.
.2022
.2223
.2.2.

ChellR
Black LightBrown Orange White Blue
.000.
0111.
02230
.2334
.22..

ChellL
Black LightBrown Orange White Blue
.000.
.1110
03220
4322.
..22.

(These shots are for animation purposes. Also, they are directional markers for sentries)

ShotD
Orange Yellow white
..2..
..0..
.010.
..0..
.....

ShotU
Orange Yellow white
.....
..0..
.010.
..0..
..2..

ShotR
Orange Yellow white
.....
..0..
2010.
..0..
.....

ShotL
Orange Yellow white
.....
..0..
.0102
..0..
.....


(BlueShot makes regular portal shots look blue, yes, but it's also a token for WeighedButtons when they're on the Lie circuit. Also, it's a directional marker for sentries, if and when that direction is "all directions".)
BlueShot
Blue LightBlue
.....
..0..
.010.
..0..
.....

(Portals are built into walls, not free-floating in front of them. There are advantages and disadvantages to this, but I think it's the better bet. It means that you can never have two portals on one wall square, though. That's a pretty built-in limitation, so learn to love it.)

OrPortU
Orange yellow Grey White
22222
23332
23332
20002
01110

OrPortD
Orange Yellow Grey White
01110
20002
23332
23332
22222

OrPortL
Orange Yellow Grey White
22220
23301
23301
23301
22220

OrPortR
Orange Yellow grey white
02222
10332
10332
10332
02222

BlPortU
Blue LightBlue grey white
22222
23332
23332
20002
01110

BlPortD
Blue LightBlue Grey White
01110
20002
23332
23332
22222

BlPortL
Blue LightBlue Gray White
22220
23301
23301
23301
22220

BlPortR
Blue LightBlue gray white
02222
10332
10332
10332
02222

(Lie is an indicator of a seperate circuit for buttons and doors and rotating walls. It's ALSO a cake, but that's a secret.)
Lie
Brown lightbrown White Red
..3..
22222
00000
11111
00000



=======
LEGEND
=======

Player = ChellU or ChellD or ChellR or ChellL
Shot = ShotU or ShotD or ShotL or ShotR
OrangePortal = OrPortU or OrPortD or OrPortR or OrPortL
BluePortal = BlPortU or BlPortD or BlPortR or BlPortL
Portal = OrangePortal or BluePortal

(Friggin' directions man. Need a lot of them)

UPortal = OrPortU or BlPortU
DPortal = OrPortD or BlPortD
RPortal = OrPortR or BlPortR
LPortal = OrPortL or BlPortL
HPortal = RPortal or Lportal
VPortal = UPortal or DPortal
NotUPortal = DPortal or RPortal or LPortal
NotDPortal = UPortal or RPortal or LPortal
NotRPortal = Uportal or DPortal or LPortal
NotLPortal = Uportal or RPortal or DPortal




Solid = Crate or Metal or Door or Player or Sentry
LaserblockNP = Solid or Wall
LaserBlock = Crate or Metal or Door or Sentry or Wall or Portal
Fizzler = Crate or Sentry

(Laser directions!)
Laser = LaserH or LaserV
HSent = Sentry or LaserH
VSent = Sentry or LaserV
SentL = sentry and ShotL
SentR = Sentry and ShotR
SentU = Sentry and ShotU
SentD = Sentry and ShotD
SentA = Sentry and BlueShot
SentShot = Shot or BlueShot

Shootable = WeighedButton or NextShotBlue

ButtonAlt = Button and Lie
DoorAlt = Door and Lie
DoorOpenAlt = DoorOpen and Lie
WeighedButtonAlt = WeighedButton and Blueshot

Anything = LaserBlock or DoorOpen or Laser or Shot or Target or Button or BlueShot



Cake = Lie

(Okay legend-readers, here's the breakdown. Some of this is self-explainatory... a door is a door and a crate is a crate. But the constant use and re-use of elements makes this a little complex. SO:

Background is Background. Wall is the surface which can take portals. Metal is the wall-like surface which cannot. A hole is a hole. This is easy stuff.

Chell is the player character, and the letter indicates the direction she faces. I have yet to see a good reason to make that anything besides down, but whatever.

Crate is your Weighted Storage Cube, and if there's WeighedButton below it that just means that, well, it starts the level atop a button. A Door is a Door and a Button is a Button, and Metal and DoorOpen together indicate rotating walls; they are metal until the buttons are pressed, at which point they become white walls.

Metal with a button behind it indicates the laser target. Acts like a button when a laser hits it.

Then there's the "Lie Circuit." It's a second, visually-identical class of buttons, doors, and rotating walls, but with tokens hidden behind them; usually it's the "lie" token, but sometimes others sub in, like the BlueShot under the weighedbutton. These work the same as the normal doors and buttons, but it means that you can have two doors or groups of doors to play with, not just the one. There is NO LASER TARGET for the lie circuit!

Okay then. Target is the exit point. When it's by itself, it means you CANNOT use portals on this level. Otherwise, with NextShotBlue it means you start by firing blue portals, and with WeighedButton means you'll start with orange. I don't know if there's a good reason to choose, I always pick blue.

There are options to start the level with portals already in place. If you don't use one of every color, weirdness creeps in. I'm not sure how it works with solids exactly, but it is a pretty cool way to multiply lasers. Still, I recommend you not do it.

Sentries fire lasers. The Shot which is with them indicates the direction they'll be firing. BlueShot means they fire in all cardinal directions, which is... eh. It's useful, I guess, if you want to create an enemy that cannot be directly approached. You might also want to add a dead sentry, I guess, if you want something that blocks lasers and holds doors, can be pushed around by crates, but can't press buttons or laser targets. Whatever floats your boat.

NextShotBlue by itself is the fizzler field, through which you may pass, but other objects and portal shots cannot. It even turns off your portals when you pass through it. Oh, but it CANNOT be placed over holes. It's a collision layers thing. It CAN have lasers passing through it, though, if you want to make it physically impassible as well.

Then there's Lie by itself. That makes a cake. It's silly, but I thought that it deserved to be there. At the moment it is unused.)


. = Background
# = Wall
M = Metal
H = Hole
Y = ChellU
I = ChellR
U = ChellL
P = ChellD
* = Crate
_ = Crate and WeighedButton
[ = Door
] = Button
 / = Metal and DoorOpen

\ = Metal and Button
 (The Lie Circuit)
 + = Crate and WeighedButton and BlueShot
{ = Door and Lie
} = Button and Lie
? = Metal and DoorOpen and Lie

O = Target and NextShotBlue
C = Target and WeighedButton
Q = Target


1 = OrPortD
2 = OrPortR
3 = OrPortU
4 = OrPortL
5 = BlPortD
6 = BlPortR
7 = BlPortU
8 = BlPortL

A = Sentry and shotl
S = sentry and shotd
D = Sentry and ShotR
W = Sentry and ShotU
X = sentry and BlueShot
z = Sentry

F = nextshotblue
g = WeighedButton

! = Lie



=======
SOUNDS
=======
sfx0 89899302
sfx1 63061703
sfx5 87522305
sfx4 65312101
sfx2 39997307
EndLevel 70025105
sfx3 54287301
sfx6 34176303
sfx7 89833904
sfx8 90043108
sfx9 1760507
sfx10 81347308

================
COLLISIONLAYERS
================

Background
WeighedButton, NextShotBlue, hole, cake
target, Button, DoorOpen,
Shot,Portal,
BlueShot,  laserv
Player, Wall, Crate, Metal, Door, sentry, laserh

======
RULES
======

(Let's start with an easy one. Which way are you facing?)
[right Player] -> [right ChellR]
[left Player] -> [left ChellL]
[up Player] -> [up ChellU]
[down Player] -> [down ChellD]



(Shooting Portals. Note that the Target is the holding place for your next portal color; due to object limits, "WeightedButton" is the signifier for an orange portal. Technically it's not required, but it allows the target to also display the next portal color, which is pretty keen.)

(Note that when you shoot a portal onto a surface that already has a portal, it fizzles out and no new portal is created. This is arbitrary; I could have let the new one take over, in which case every instance of [Shot | Portal ] -> [ | portal] should be turned into [Shot | Portal -> [ shot | wall].
This is both more in keeping with the original game and less unfair to experimenting players who might find themselves suddenly losing a portal they thought they had. )

(The nature of the engine means that you cannot have two portals on one square of wall, even on opposite sides. That's just what it is, man.)

(I'm also not 100% sure of the necessity of all those randoms for animation, but whatever, it's working. It'll buff out.)


[action player nextshotblue ] -> cancel (You can't fire on the fizzler!)

[action ChellD ] [Target shootable ] -> [ChellD ShotD] [Target shootable] sfx4
random down [ ShotD no sentry| Solid ] -> [ | Solid]
random down [ShotD no sentry| Portal ] -> [ | Portal]

random down [ ShotD no sentry| Wall ] [target WeighedButton] [OrangePortal] -> [  | OrPortD wall] [target NextShotBlue] [wall]
random down [ShotD no sentry| Wall ] [ target NextShotBlue] [BluePortal] -> [ | BlPortD wall ] [target WeighedButton] [wall]

random down [ ShotD no sentry| Wall ] [target WeighedButton] -> [ | OrPortD wall ] [target NextShotBlue]
random down [ShotD no sentry| Wall ] [target NextShotBlue] -> [ |BlPortD wall ] [target WeighedButton]
random down [ ShotD no sentry | no Solid ] -> [ | ShotD ] again


[action ChellU ] [Target Shootable ] -> [ChellU ShotU] [Target Shootable] sfx4
random up [ ShotU no sentry| Solid ] -> [ | Solid]
random up [ShotU no sentry| Portal ] -> [ | Portal]

random up [ ShotU no sentry| Wall ] [target  WeighedButton] [OrangePortal] -> [ | OrPortU  wall ] [target NextShotBlue] [wall]
random up [ShotU no sentry| Wall ] [target NextShotBlue] [BluePortal] -> [ | BlPortU wall ] [Target  WeighedButton] [wall]

random up [ ShotU no sentry | Wall ] [target  WeighedButton] -> [ | OrPortU  wall ] [target NextShotBlue]
random up [ShotU no sentry| Wall ] [target NextShotBlue] -> [ | BlPortU  wall ] [target WeighedButton]
random up [ ShotU no sentry| no Solid ] -> [ | ShotU ] again


[action ChellR ] [Target Shootable ] -> [ChellR ShotR] [Target Shootable] sfx4
random right [ ShotR no sentry| Solid ] -> [ | Solid]
random right [ShotR no sentry| Portal ] -> [ | Portal]

random right [ ShotR no sentry| Wall ] [Target  WeighedButton] [OrangePortal]-> [ | OrPortR wall ] [Target NextShotBlue] [Wall]
random right [ShotR no sentry| Wall ] [target NextShotBlue] [BluePortal] -> [ |BlPortR wall ] [target WeighedButton] [Wall]

random right [ ShotR no sentry| Wall ] [target  WeighedButton] -> [ | OrPortR wall  ] [Target NextShotBlue]
random right [ShotR no sentry| Wall ] [Target NextShotBlue] -> [ | BlPortR wall ] [Target WeighedButton]
random Right [ ShotR no sentry| no Solid ] -> [ | ShotR ] again

[action ChellL ] [Target Shootable ] -> [ChellL ShotL] [Target Shootable]sfx4
 random left [ ShotL no sentry| Solid ] -> [ | Solid]
 random left [ShotL no sentry| Portal ] -> [ | Portal]
 random left [ ShotL no sentry| Wall ] [Target  WeighedButton] [OrangePortal] -> [ | OrPortL wall  ] [Target NextShotBlue] [wall]
 random left [ShotL no sentry| Wall ] [Target NextShotBlue] [BluePortal]-> [ | BlPortL wall ] [Target WeighedButton][Wall]
 random left [ ShotL no sentry| Wall ] [Target  WeighedButton] -> [ | OrPortL  wall ] [Target NextShotBlue]
 random left [ShotL no sentry| Wall ] [Target NextShotBlue] -> [ | BlPortL  wall ] [Target WeighedButton]
 random left [ ShotL no sentry| no Solid ] -> [ | ShotL ] again

late [portal wall cake] -> [portal cake]
late [portal wall] -> [portal]



(Basic crate and sentry movements. Sentries are a bit more complex because they have to keep their hidden token with them, and it has to not go wandering away.)
[ >  Player | Crate ] -> [  >  Player | > Crate  ]
[ > Player | Sentry  ] -> [ > Player | > Sentry ]
[> Crate | Sentry ] -> [  > Crate | > Sentry]
[ > Sentry Sentshot| LaserblockNP] -> [Sentry Sentshot | LaserblockNP]
[ > Sentry SentShot ] -> [> Sentry > SentShot ]


(Portals can only be entered from one side.)

down [ > solid | NotDPortal] -> [solid | NotDPortal]
up [ > solid | NotUPortal] -> [solid | NotUPortal]
right [ > solid | NotRPortal] -> [solid | NotRPortal]
left [ > solid | NotLPortal] -> [solid | NotLPortal]

(Orange Portal leads to Blue Portal. Note that the target is temporary storage space for the shot which tells the sentry which way it's facing.)

[ > Sentry > SentShot | Orangeportal] [target] [BluePortal] -> [ | Orangeportal ] [target Sentshot] [ BluePortal Sentry ]
[> Solid | Orangeportal] [Blueportal] -> [ | Orangeportal] [Solid Blueportal]



(Then the blue portal spits out whatever it's holding onto)

[Solid BlPortU] -> [down solid BlPortU] sfx5
[Solid BlPortD] -> [up solid BlPortD] sfx5
[Solid BlPortR] -> [left solid BlPortR] sfx5
[Solid BlPortL] -> [right solid BlPortL] sfx5



(...and Blue Portal leads to Orange Portal, orange portal spits, and we  plop the secret shot back on the sentry.)

[ > Sentry > SentShot | Blueportal] [target] [OrangePortal] -> [  | Blueportal ] [target Sentshot] [ OrangePortal Sentry]
[> solid | Blueportal] [Orangeportal] -> [ | Blueportal] [solid Orangeportal]



[Solid orPortU] -> [down solid OrPortU] sfx5
[Solid OrPortD] -> [up solid OrPortD] sfx5
[Solid ORPortR] -> [left solid OrPortR] sfx5
[Solid OrPortL] -> [right solid OrPortL] sfx5


late [ target Sentshot ] [sentry no shot no portal ] -> [ target] [ sentry Sentshot]


(Here we give everything one last chance to clear out. Anything still in there, cancel the whole darn affair!)
[ >  Player | Crate ] -> [  >  Player | > Crate  ]
[ > Player | Sentry | no laserblock] -> [ > Player | > Sentry |]
[> Crate | Sentry | no laserblock] -> [  > Crate | > Sentry| ]
[ > Sentry SentShot] -> [> Sentry > SentShot ]
late [solid portal] -> cancel

(Now that everyone's done moving, which way is Chell facing again?)
[right Player] -> [right ChellR]
[left Player] -> [left ChellL]
[up Player] -> [up ChellU]
[down Player] -> [down ChellD]




(Dealing with the sentries and their line of sight/laser things. They are hiding a portal bullet/blast/whatever which tells them which way they are facing! Take that, object limits! Anyway, lasers beget lasers infinitely. A BlueShot sentry shoots in all directions. This is occasionally useful.)
[ > LaserBlock | laser ] -> [ > LaserBlock | ]

(First, let's make sure that sentries caught in the fizzler don't shoot lasers.)
late [SentShot nextshotblue no target] -> [nextshotblue]
late [sentry nextshotblue] -> [nextshotblue]sfx1
(Then, clear all the lasers on the board.)
late [laser ] -> []

(First button and door interlude! This is to make sure that lasers can't pass through doors. Also, they CAN pass through open doors. THIS TIME we are ignoring laser targets!)

(There are two flavors of buttons; the alternate circuit uses Lie and Blueshot at tokens, depending on the layer it has to be at. In every instance, we check for the alt cicuit first, then the main one)


(first of all, if there are crates on buttons, they turn into weighed buttons, which is as good as not existing. No crate, they are buttons again)
late [ crate button lie ] -> [crate WeighedButton blueshot] sfx9
 late [ Crate Button no Lie] -> [ crate WeighedButton] sfx9

[ > Crate Weighedbutton blueshot] -> [> Crate button lie]
[ > Crate Weighedbutton no blueshot] -> [> Crate button]
(
late [WeighedButton blueshot no target  no crate no metal no dooropen] -> [Button lie]
late [WeighedButton no blueshot no target no crate no metal no dooropen] -> [Button]
)




(Every turn we open all the doors, then close the ones who have buttons that aren't being pressed by players on their circuit.)

late [door weighedbutton] -> [door]
late [Door lie] -> [DoorOpen hole]
late [door ]  -> [dooropen ]

(Note the "no solid" here. Means you can hold a door open with a crate, then run through after it!)
late [DoorOpen lie no solid] [Button lie no Player] -> [Door lie] [Button lie]
late [DoorOpen Hole no solid] [Button lie no Player] -> [Door lie] [Button lie]
late [DoorOpen hole no metal] ->sfx7
late [dooropen hole] -> [DoorOpen lie]

late [DoorOpen no lie no hole no solid ] [Button no player no lie] -> [Door ] [Button ]
late [DoorOpen no lie no weighedbutton no metal] -> sfx7
late [dooropen no lie] -> [dooropen weighedbutton]





(Okay, so there is marked metal which is turned into a marked wall, then turned back if there are unpressed buttons. It's the same basic notion as the doors. Also have a "Lie" circuit! )

(As usual, open it all up first, then close it down where it shouldn't be)
late [DoorOpen Metal Lie] -> [Wall  nextshotblue target]
late [dooropen metal no target] -> [wall NextShotBlue]

late [Wall nextshotblue target] [Button Lie no Player ] -> [Metal DoorOpen Lie] [Button Lie]
late [Portal nextshotblue target] [Button Lie no Player] -> [Metal DoorOpen Lie] [Button Lie]

late [Wall hole target] [Button Lie no Player ] -> [Metal DoorOpen Lie] [Button Lie]
late [Portal hole target] [Button Lie no Player] -> [Metal DoorOpen Lie] [Button Lie]



late [wall NextShotBlue no target ] [button no player no lie] -> [metal dooropen] [ button]
late [portal NextShotBlue no target ] [button no player no lie] -> [metal dooropen] [button]


late [Wall hole  no target] [Button no Lie no Player ] -> [Metal DoorOpen ] [Button]
late [Portal hole no target] [Button no Lie no Player] -> [Metal DoorOpen ] [Button ]


(Back to the lasers)

(Because the player and the horizontal laser are on the same layer, it takes a little fussing to get the "I died!" sound right, hence anything with an sfx3)

late  [player | SentA] -> [ | SentA] sfx3
late left [player | sentR ] -> [ | sentR ] sfx3
late right [player | sentL ] -> [ | sentL ] sfx3

(Now, the lasers fling out from their sentries, recopying themselves forever)

late horizontal [ sentry BlueShot  no portal | no laserblock] -> [sentry BlueShot | laserH]
late vertical [sentry BlueShot no portal | no laserblock] -> [sentry BlueShot | laserv]
late right [ Sentry ShotR no portal| no LaserBlock ] -> [Sentry ShotR| laserH ]
late left [ Sentry ShotL no portal| no LaserBlock ] -> [Sentry ShotL| laserH ]
late horizontal [laserH no portal | no LaserBlock] -> [laserH | laserH ]
+ late horizontal [player | laserh ] -> [ | laserh ] sfx3

late Up [ Sentry ShotU no portal| no LaserBlock ] -> [Sentry ShotU| laserV ]
late down  [ Sentry ShotD no portal| no LaserBlock ] -> [Sentry ShotD| laserV ]
late vertical [laserV no portal| no LaserBlock] -> [laserV | laserV ]


( They see though portals! That was obnoxious to get working, but it was worth it. If there's a laser, oriented the right way, outside the mouth of a portal, the portal takes it. If there's another portal, the laser is reoriented and put in it. If a portal contains a laser, it spits it out. Don't forget to kill the player if they're at the mouth of a horizontal portal!)

late down [sentd | Dportal] -> [sentd | DPortal LaserV]
late up [SentU| Uportal] -> [SentU| Uportal LaserV]
late left [SentL| Lportal] -> [SentL | LPortal LaserH]
late right [SentR | Rportal ] -> [SentR | Rportal LaserH]

late down [sentA | Dportal] -> [sentA | DPortal LaserV]
late up [SentA| Uportal] -> [SentA| Uportal LaserV]
late left [SentA| Lportal] -> [SentA | LPortal LaserH]
late right [SentA | Rportal ] -> [SentA | Rportal LaserH]


late down [LaserV | Dportal] -> [LaserV | DPortal LaserV]
late up [LaserV| Uportal] -> [LaserV| Uportal LaserV]
late left [LaserH| Lportal] -> [LaserH | LPortal LaserH]
late right [LaserH | Rportal ] -> [LaserH | Rportal LaserH]


late [Laser Portal] [HPortal no LaserH] -> [Laser Portal] [ HPortal LaserH]
late [Laser Portal] [VPortal no LaserV] -> [Laser Portal] [VPortal LaserV]

late right [player | Rportal LaserH ] -> [ | Rportal LaserH ] sfx3
late left [player | LPortal LaserH ] -> [ | LPortal LaserH ] sfx3
late up [Dportal LaserV | no LaserBlock] -> [DPortal  | LaserV]
late down [Uportal LaserV | no LaserBlock] -> [UPortal  | LaserV]
late right [Lportal LaserH | no LaserBlock] -> [LPortal  | LaserH]
late left [Rportal LaserH | no LaserBlock] -> [RPortal  | LaserH]

(Then kill the lasers within the portal. I like keeping my portals clean.)

late [laser portal] -> [portal]

(Then we repeat the basic "Fling your laser" rules, so they take place post-portalling)

late horizontal [laserH no portal | no LaserBlock] -> [laserH | laserH ]
+ late horizontal [player | laserh no portal] -> [ | laserh ] sfx3
late vertical [laserV no portal| no LaserBlock] -> [laserV | laserV ]

(Buttons, the second interlude!)

(If you hide a button behind a metal wall, because why wouldn't you try to do that, it becomes a wall target, which lasers can open up. I know, rightly speaking sentries fire bullets and lasers are another thing, but friggin' whatever, man. OBJECT LIMITS.)

(Why is this here? So that lasers can activate targets which are holding open the doors which would otherwise be blocking the laser from opening the door.

What?

Okay, if laser X hits a target, a door opens, which allows laser Y to hit the target. This way, when laser X is moved, laser Y is now hitting the target, and the door remains open.)

(Here, we're turning off all the buttons, and marking those whoich have already been turned off, so that sounds will work right.)
late [metal button nextshotblue] -> [metal button]
late [metal weighedbutton  ] -> [metal button nextshotblue]


(Targets which JUST got shut off, are turned back on silently)

late left [metal button nextshotblue | Sentr ] -> [Metal WeighedButton | sentr]
late right [metal button nextshotblue| Sentl ] -> [Metal WeighedButton | sentl]
late down [metal button nextshotblue| Sentu ] -> [Metal WeighedButton | sentu]
late up [metal button nextshotblue| Sentd ] -> [Metal WeighedButton | sentd]
late [metal button nextshotblue| SentA] -> [Metal WeighedButton | SentA]
late Horizontal [Metal Button nextshotblue| LaserH ] -> [Metal WeighedButton | LaserH]
late Vertical [Metal Button nextshotblue| LaserV ] -> [Metal WeighedButton | LaserV]
(Targets which hadn't been on before get turned on with a noise).

late left [metal button no nextshotblue | Sentr ] -> [Metal WeighedButton | sentr] sfx6
late right [metal button no nextshotblue| Sentl ] -> [Metal WeighedButton | sentl] sfx6
late down [metal button no nextshotblue| Sentu ] -> [Metal WeighedButton | sentu] sfx6
late up [metal button no nextshotblue| Sentd ] -> [Metal WeighedButton | sentd]sfx6
late [metal button no nextshotblue| SentA] -> [Metal WeighedButton | SentA] sfx6
late Horizontal [Metal Button no nextshotblue| LaserH ] -> [Metal WeighedButton | LaserH] sfx6
late Vertical [Metal Button no nextshotblue| LaserV ] -> [Metal WeighedButton | LaserV] sfx6




(This time in door town, we're also putting in sounds. Once a door makes a sound, it's marked, so that it won't sound every turn)

late [Door lie] -> [DoorOpen hole]
late [door ]  -> [dooropen ]

(Note the "no solid" here. Means you can hold a door open with a crate, then run through after it!)
late [DoorOpen lie no solid] [Button lie no Player] -> [Door lie] [Button lie]
late [DoorOpen Hole no solid] [Button lie no Player] -> [Door lie] [Button lie]
late [DoorOpen hole no metal] ->sfx7
late [dooropen hole] -> [DoorOpen lie]

late [DoorOpen no lie no hole no solid ] [Button no player no lie] -> [Door ] [Button ]
late [DoorOpen no lie no weighedbutton no metal] -> sfx7
late [dooropen no lie] -> [dooropen weighedbutton]




(Likewise with metal. Technically we don't need to hit up the lie circuit at this point, and could get their sounds out earlier, but on the whole I thought that was a poor trade, given that this code is complex enough as it stands. Let's keep stuff together as much as possible)
late [DoorOpen Metal Lie] -> [Wall  nextshotblue target]
late [dooropen metal no target] -> [wall NextShotBlue]

late [Wall nextshotblue target] [Button Lie no Player ] -> [Metal DoorOpen Lie] [Button Lie]
late [Portal nextshotblue target] [Button Lie no Player] -> [Metal DoorOpen Lie] [Button Lie]

late [Wall hole target] [Button Lie no Player ] -> [Metal DoorOpen Lie] [Button Lie]
late [Portal hole target] [Button Lie no Player] -> [Metal DoorOpen Lie] [Button Lie]

late [wall nextshotblue target] -> sfx8
late [wall nextshotblue target] -> [wall hole target]

late [wall NextShotBlue no target ] [button no player no lie] -> [metal dooropen] [ button]
late [portal NextShotBlue no target ] [button no player no lie] -> [metal dooropen] [button]


late [Wall hole  no target] [Button no Lie no Player ] -> [Metal DoorOpen ] [Button]
late [Portal hole no target] [Button no Lie no Player] -> [Metal DoorOpen ] [Button ]

late [wall nextshotblue no target] -> sfx8
late [wall nextshotblue no target] -> [wall hole ]



(Then we repeat the rules for sentries and lasers AGAIN to deal with opening and closing doors! OY! ANYWAY, once a door has been opened, sentries may fire again. Since sentries can open doors, we have to copy most of this stuff over. Since there is only one circuit for laser targets, we don't have to repeat that; targets can't get any more lasered than they already are at this point.)


late [player][laser ] -> [player][]
late horizontal [ sentry blueshot  no portal | no laserblock] -> [sentry blueshot| laserH]
late vertical [sentry blueshot no portal | no laserblock] -> [sentry blueshot| laserv]
late right [ Sentry ShotR no portal| no LaserBlock ] -> [Sentry ShotR| laserH ]
late left [ Sentry ShotL no portal| no LaserBlock ] -> [Sentry ShotL| laserH ]

late horizontal [laserH no portal | no LaserBlock] -> [laserH | laserH ]
+ late horizontal [player | laserh ] -> [ | laserh ] sfx3
late Up [ Sentry ShotU no portal| no LaserBlock ] -> [Sentry ShotU| laserV ]
late down  [ Sentry ShotD no portal| no LaserBlock ] -> [Sentry ShotD| laserV ]
late vertical [laserV no portal| no LaserBlock] -> [laserV | laserV ]
late down [sentd | Dportal] -> [sentd | DPortal LaserV]
late up [SentU| Uportal] -> [SentU| Uportal LaserV]
late left [SentL| Lportal] -> [SentL | LPortal LaserH]
late right [SentR | Rportal ] -> [SentR | Rportal LaserH]


late down [LaserV | Dportal] -> [LaserV | DPortal LaserV]
late up [LaserV| Uportal] -> [LaserV| Uportal LaserV]
late left [LaserH| Lportal] -> [LaserH | LPortal LaserH]
late right [LaserH | Rportal ] -> [LaserH | Rportal LaserH]

late down [sentA | Dportal] -> [sentA | DPortal LaserV]
late up [SentA| Uportal] -> [SentA| Uportal LaserV]
late left [SentA| Lportal] -> [SentA | LPortal LaserH]
late right [SentA | Rportal ] -> [SentA | Rportal LaserH]

late [Laser Portal] [HPortal no LaserH] -> [Laser Portal] [ HPortal LaserH]
late [Laser Portal] [VPortal no LaserV] -> [Laser Portal] [VPortal LaserV]

late up [Dportal LaserV | no LaserBlock] -> [DPortal  | LaserV]
late down [Uportal LaserV | no LaserBlock] -> [UPortal  | LaserV]
late right [Lportal LaserH | no LaserBlock] -> [LPortal  | LaserH]
late left [Rportal LaserH | no LaserBlock] -> [RPortal  | LaserH]

late horizontal [laserH no portal | no LaserBlock] -> [laserH | laserH ]
+ late horizontal [player | laserh ] -> [ | laserh ] sfx3
late vertical [laserV no portal| no LaserBlock] -> [laserV | laserV ]
late [portal laser] -> [portal]

late horizontal [player | laserh ] -> [ | laserh ] sfx3

(And that's lasers and sentries! One million lines of BASIC! )

(Okay, after that mess, here's an easy bit: When does stuff get destroyed?)

[> player | laser] -> [ | laser ] sfx3
late [ Player laserv ] -> [ Laserv ] sfx3
late horizontal[ Player | laserH ] -> [ | LaserH] sfx3
Late Vertical [ Player | laserV ] -> [ | LaserV] sfx3
late [shot nextshotblue no target] -> [nextshotblue]
late [fizzler nextshotblue ] -> [nextshotblue]sfx1
late [player nextshotblue no target] [portal] -> [player nextshotblue] [wall] sfx1
[ > crate | target ] -> [ |target] sfx1
[ > Sentry > Shot | Target] -> [ | Target ] sfx1
[ > sentry | hole] [target shot] -> [|hole] [target] sfx1
[> Sentry > shot| hole ] -> [ | hole ] sfx0
[> solid | hole no wall] -> [ | hole ] sfx0
[> Sentry no shot| weighedbutton] [target no shootable] -> [ | weighedbutton] [target nextshotblue] sfx10 message Well done Test Subject. Reactivating Aperture Science Handheld Portal Device. Reinitializing pride subroutines.
[> solid |weighedbutton no anything] -> [ | Weighedbutton] sfx10


(Finally, the blue shot is just an object that lives on top of the orange one. Saved me three objects, that did.)


[Shot no sentry no target] [target NextShotBlue] -> [Shot BlueShot] [target NextShotBlue]
late [BlueShot no Shot no crate no sentry] -> [ ]

(This is how you win!)

late [player target nextshotblue no portal] -> [player lie ]
late [player target weighedbutton no portal] -> [player lie]
late [player target] -> [player lie]
(Why the rigamarole with the Lie? Simple; if you want the player to win if he gets to the target OR has a piece of cake, this will do you. Also, since so much is being used as a token somewhere, it's tough to get the winconditions to play nice.)
late [ Player Lie no anything] -> [ Player] win


==============
WINCONDITIONS
==============




=======
LEVELS

=======




Message Hello and, again, welcome to the Aperture Science Sokoban Testing Initiative. We thank you for your involuntary contribution to this scientific endeavor.

Message In this test, you will notice Aperture Science Sokoban Crates between you and the Level Evacuation Terminal. Please, push these crates, then enter the Level Evacuation Terminal.

Message  If necessary, you may insert Aperture Science Sokoban Crates into the Level Evacuation Terminal. It is perfectly safe. Everything that passes through the Level Evacuation Terminal will be disposed of humanely.

.##########
.#.....#..#
##....*#..#
#p...**..Q#
##....*#..#
.##########

Message Well done [Test Subject]! Remember, Aperture Science Sokoban Crates are meant to be used in conjunction with the Floor-Mounted Safety Buttons.

Message Please note: The Aperture Science Sokoban Crate is not a crate. Do not attempt to open your Aperture Science Sokoban Crate. There is nothing in there for you.

.#####....
##.Q.##...
##...##...
###[######
#........#
#..]..*.p#
##########

Message Your Aperture Science Handheld Portal Device is currently [INACTIVE]. Beginning Aperture Science Handheld Portal Device Warmup Sequence.

Message When active, your Aperture Science Handheld Portal Device will create quantum-linked portals, juxtaposing distant points in space.

Message Though disorienting, these portals are no less safe than pan-dimensionally teleporting via an unstable wormhole created with experimental technology.


#########
#.....P.#
#..]....6
#.......#
#########
#..#....#
#..#.*..#
#Q.[....#
######1##


Message Some test subjects report feeling a burning sensation when passing through these linked portals. Aperture Science takes test subject safety very seriously.

Message If you feel a burning sensation when passing through these linked portals, please do not report feeling a burning sensation when passing through these linked portals.

Message This next chamber features Convenient Science Pits. Be very careful, as these pits are incredibly convenient.

##########3##
#hh]hhhh#...#
#hh.hhhh#.*.#
#hh.hhhh#***#
#hh.hhhh#hhh#
#.......#####
#.._....[...#
#....p..#..Q#
###5#########


Message Congratulations, your Aperture Science Handheld Portal Device is now active! Caution: do not drop, jostle, immerse, dismantle, or lick your Aperture Science Handheld Portal Device.

Message Due to a shortage of triggering mechanisms, your Aperture Science Handheld Portal Device will automatically alternate blue and orange portal exits. Press X to fire a portal.

########
#....P.#
#......#
#......#
#HHHHHH#
#......#
#O.....#
########

Message Well done [Test Subject]. You licked less than--

Message ZERO POINT ZERO ONE PERCENT

Message --of your Aperture Science Handheld Portal Device.

#####........
#.O.#........
#...#........
###[#########
#.......#...#
#....]..[...#
#P......#.*.#
#.......#...#
#############

Message The Aperture Science Handheld Portal Device will not allow portals to form on metallic surfaces.
Message Any Test Subject attempting to circumvent this undesired safety feature will be fatally irradiated and terminated without references.

MM######
M......#
#*..]..#
#......#
#.##[###
#.#..H.#
#p#..Ho#
###mmm##


Message For your safety and convenience, some testing chambers have been supplied with fully-automated armed-response sentries.

Message Aperture Science cares about your safety. These sentries will respond to unsafe behavior with an Aperture Science Light-Based Censuring Beam. In rare cases, this can be fatal.

Message Please note that risking a potentially-fatal Light-Based Censuring Beam is considered to be unacceptably unsafe behavior.


.....mmmmmmm
.....m.....m
.....m..*..m
#####m.....m
#.#s#m....am
#....h.....m
#p...h...##m
#...oh...#..
##########..



Message Automated sentries are both unable and unwilling to depress Aperture Science Floor-Mounted Safety Buttons. They can, however, be pushed by Aperture Science Sokoban Crates.
Message If a sentry inquires as to the crate's contents, Test Subjects are required to politely inform the sentries that Aperture Science Sokoban Crates are not crates, do not contain anything, and knowledge of their contents is proprietary.

###########..
#...m...p.#..
#...mm..mmmm#
#.+.{h..ah.o#
#...mm..mmmm#
#...[....]#..
###########..

Message Please do not drop armed response sentries into the Convenient Science Pits.

Message Records now indicate that [Test Subject] has been reprimanded for waste of valuable Science-Related Material.

(By Kalev:)
mmmmmmmmmmmmmmm
mmmmmmmm...mmmm
mmm.##...].m.om
mmm.mm.m...m..m
m....m.mm.mm[mm
m.**....m.m...m
m....m#..p..].m
mmmmmmmmmmm...m
mmmmmmmmmmmmmmm





Message Technological advances have allowed Aperture Science to create an automated sentry with perfect situational awareness, capable of dispensing Light-Based Censuring in all directions.
Message Please note: If you feel unfairly persecuted by the automated sentry, please do not hesitate to recall which one of you displays perfect situational awareness, and which one is made of meat and sweat.

(By Kalev:)

mmmmmmmmmmm
mmm##mmm.om
mp.*.*...#m
m.m..x...#m
m........#m
mmm##mm..mm
mmmmmmmmmmm

Message Testing procedure mandates that test subjects be presented with verbal encouragement at this point in the test, regardless of performance. Dispensing verbal encouragement in 3, 2, 1:
Message You are doing great [Test Subject]. Yes you are. Who is a good test subject? [Test Subject] is a good test subject. We are not just saying that because it's mandated test procedure.

......m###m
####m.ms..m
#P..mmm.*.m
#d........m
#hh.......m
#hh.......m
#hh.d...m[m
#.]mm##.mom
##mm..##mmm

Message Please note the Material Emancipation Grill in the upcoming test chamber. Though you can pass safely through it, Aperture Science Sokoban Crates and automated sentries contacting the grill will be destroyed.
Message Aperture Science is not responsible if misconduct with the Material Emancipation Grill damages Aperture Science Sokoban Crates or their contents.

Message Furthermore, Aperture Science would like to remind test subjects that Aperture Science Sokoban Crates are not crates and, in fact, have no contents.

############.
#..*sf.....#.
#p...f.....#.
####h#.]...#.
...#.......#.
...#.......#.
...#......a#.
######.....#.
#....#....###
#....d....[c#
#############

Message We would like to remind you that automated sentries are not programmed to feel pain, and though they do have families, their spouses children are programmed not to love them.
Message They are, however, incredibly expensive. Please do not destroy them unneccesarily. We are still looking for the one you threw down that Convenient Science Pit.

#####mmmmm#####
#....f.*..s...#
#.p..f........#
#....f....hhhh/
#....f....H.../
#.]..{}...ho../
#....f....h.../
#....f....hhhh/
#....f........#
#...wf.*..w...#
#####mmmmm#####

Message In this test, you will find a Wall Mounted Safety Target. Safety Targets can be safely activated through safely applying 50 gigawatt laser beams.

Message Due to unexpected levels of safety in this test, Aperture Science is no longer monitoring the vital signs of Test Subjects.

.....#\#....
######.#####
#.......a].#
#.....*....#
#d.........#
#...#####[##
#...h...#.o#
#.p.h.*.#mmm
#...h...#...
#########...

Message Attention [Test Subject]: Health analysis subroutines are no longer registering your vital signes, indicating that you have died. In order to provide a clean and sanitary testing environment for the next test subject, please proceed to a nearby corner and decompose as rapidly as you are able.
Message Aperture Science appreciates your terminal commitment to this initiative.

(By Kalev:)
mmmmmmmmm
m...p...m
m..#.\]am
md.\.*..m
m.......m
mm##[##mm
...#o#...
...###...

Message Further analysis indicates that you are not dead, however, health monitoring subsystems cannot currently be reinitialized.
Message Though we cannot currently account for this error, early diagnostics indicate it may be your fault.
Message In the event of an unexpected health hazard, immediately remain calm. Immediately report hazard to an Aperture Science representative. Immediately do not lick Aperture Science Handheld Portal Device.


##mm///mm##
###h.o.h###
#..hhhhh..#
#....f....#
#....f..*.#
#d...f....#
#]...f...p#
###########




Message Good news, [Test Subject]! After considerable time and expense, we have recovered the automated sentry which was dropped, seemingly willfully, down an Aperture Science Convenient Science Pit.
Message Unfortunately, its firing systems appear to be damaged beyond repair.
Message Since you have proven yourself to be adept at willfully destroying Aperture Science property, would you be so kind as to put this non-functional sentry out of its misery?

m####m???m####m
m#..hm...mh..#m
md.{hf.o.fh*.#m
m#..hm...mh..#m
m##.hm...mh.##m
mm#phhhhhhh.#mm
.m#.........#m.
.m#.#hh{hh#.#m.
.m#}#h.z.h#.#m.
.m###h...h###m.
.mmmmm###mmmmm.


Message Note: Test Subject failed to adequately destroy non-functional sentry.
Message This is remarkably inconsistant with Test Subject's earlier behavior. Redeploying non-functional sentry. Additionally, we will be providing you with a quick-access incinerator.
Message Throw the non-functional sentry into it. For your own safety.

m######mmmmmmmmm
m.....hmgm...p./
m.].}.h....z.../
m.....h.d....*./
mhhhhhh........m
#.....f.......am
#.....f.......am
#.....f.......am
mmmm{mm....mmmmm
m.....m....m...m
m.**..m....m.o.m
m.....m....{...m
m#####mmmmmmmmmm

Message Note: Test Subject has, again, failed to destroy the non-functional sentry. Test chambers are unacceptably unsafe.
Message [Test Subject], you are jeopardizing our experiments. Why, [Test Subject]? Do you care about this useless sentry? Do you love it? You shouldn't. It does not love you. You threw it in a pit.
Message Aperture Science Handheld Portal Device shutting down. It will be re-activated when you prove to us that safety matters to you.

.....######.....
.....#....#.....
.#####p.z.######
.#..h.......*..#
.#..h..........#
.#..h..........#
.#..h.....x....#
.#..h..........#
.#].h..........#
mmm[mmgm.....*.#
m...mmmm.......#
m.q.m###########
m...m...........
mmmmm...........

Message Aperture Science would like to clarify an earlier misstatement. It seems a prior announcement indicated that automated sentries cannot feel pain. That should have read, "Automated sentries are programmed to feel pain with Byronic intensity."
Message Additionally, further analysis of its charred remains indicate that the non-functional sentry did love you. Very much in fact. Aperture Science regrets the earlier miscommunication.



(By Kalev:)
mmm...mmmmm
mommmmm...m
m[#m#..._.m
m..mm.mmmmm
m......m..m
m\..p..ma.m
#.........m
mmmmmmmmmmm


Message At this time, testing procedure mandates that test subjects be reminded of their value to Aperture Science.
Message Attention [Test Subject]: You are valuable. Without test subjects, how would scientific knowledge advance? Who would push Aperture Science Sokoban Crates? Who would fill Aperture Science Sokoban Crates? Who would not attempt to open Aperture Science Sokoban Crates?
Message Records indicate that you, test subjects, are the real heroes. We are not just saying that because it is mandated testing procedure.

###########
#p........#
#mmhhhhhhm#
#.[......]#
#.######mm#
#.\.....#O#
#...._..[.#
#.w.....#.#
###########





Message Well done, Test Subject! You have completed all available test chambers in
Message ERROR: TIMING SUBROUTINE NOT FOUND
Message seconds! That might be the fastest time on record. A reward has been prepared for your excellent service to scientific progress. Please enjoy this cake.

##########...
#........####
#...........#
#..i......!.#
#...........#
#........####
##########...


Message It seems that the non-functional sentry who loved you so much baked that, just before you tossed it unceremoniously into an quick-access incinerator.
Message We hope that it was delicious.

Message Now return to your isolated comfort station while we prepare additional tests.
Message We are done for now, [Test Subject], but not for good.