-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lights out #1273
lights out #1273
Conversation
# Summary This PR allows a recipe's effects to be applied within the same tick if `time: 0` is specified for the recipe. The previous behavior was that if the `time` of the recipe was zero, it would nonetheless behave the same as `time: 1`, and the entity updates would not be applied until the next tick. This new behavior is useful when "abusing" the `drill` command to emulate various other games via help from a system robot. # Motivation For the "Lights Out" game (#1273) I have implemented a system robot that `instant`-ly toggles the four adjacent lights and the center light when a center light is `drill`-ed by the player. The light entities are named `"off"` and `"on"`. I did some experiments to see if the system robot would react "fast enough" if the player drilled quickly in succession. # Experiments The 5x5 light grid is initially `"off"`. I moved the player robot to the center of the grid, facing `east`. From this position, I tried three command sequence variations both *before* and *after* this PR. The recipes for toggling lights specify `time: 0`. ## Before this PR ### 1. Drilling twice in succession drill down; drill left; This resulted in an error: ![no-instant-error-message](https://github.com/swarm-game/swarm/assets/261693/f22a0a28-5df7-4fe8-ac18-97504d64e3c8) so only the first `drill` got applied: ![no-instant](https://github.com/swarm-game/swarm/assets/261693/2d9e4ba7-c138-4dcb-94a6-3c7bb14ddd68) This is because I believe the sequence of events was: | Tick / Robot | Action | | --- | --- | | **Tick 1:** Player | Execute the first `drill` command, queue entity modification | | **Tick 1:** System | No changes observed | | **Tick 2:** Player | Entity modification from first `drill` is applied. Execute second `drill` command, queue second entity modifications | | **Tick 2:** System | Observe modified entity, toggle the adjacent lights | | **Tick 3:** Player | Try to apply entity modification from second `drill` command. Throw an error because the system robot has toggled the drill's target entity to `on` whereas the `drill` was initially executed when it was still `off`. | ### 2. Instant for both drills instant $ (drill down; drill left) In this case, both of the player's `drill` commands were executed, but the system robot then failed to doubly-invert one of the cells: ![instant-both-drills](https://github.com/swarm-game/swarm/assets/261693/65642fd6-3cea-4834-96fd-404da7628c66) This is due to some kind of race condition in the system robot's logic. However, it is irrelevant because the `instant` command shall not be available to the player. ### 3. Instant for first drill only, then second drill instant (drill down); drill left; This accomplished what approach number 1 was supposed to; both drill commands were applied and the two overlapping cells got properly inverted: ![instant-first-drill](https://github.com/swarm-game/swarm/assets/261693/64aab681-140d-457a-9273-943ae5b4d58d) **Explanation:** In this case, the entire drilling operation (including applying all effects to entities on the ground) was completed within the player's first tick, so the system robot updated the lights appropriately on its turn. Then, in the next tick the player robot applied another drill command, and again the system robot appropriately did another inversion on the two overlapping middle cells. ## After this PR ### 1. Drilling twice in succession drill down; drill left; Now works as expected: ![after-no-instant](https://github.com/swarm-game/swarm/assets/261693/538767d3-9832-4e5c-996e-12a9b7a2015c) ### 2. and 3. Behaved identically to before the PR.
d306d59
to
db1bd9c
Compare
db1bd9c
to
e655faf
Compare
e655faf
to
30985f2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice! I was able to solve it manually. Tried coding up an automated solution and came up with the "chasing lights" idea but then wasn't sure what to do when there were lights left in the last row. Then I read the links in the solution and I learned a lot of interesting things about this puzzle. 😄
case maybePending return $ flipSelfAndNeighbors state; | ||
end; | ||
|
||
def observe = \boardWidth. \boardHeight. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function doesn't seem to use boardWidth
and boardHeight
at all?
togglePending "on"; | ||
togglePending "off"; | ||
); | ||
observe boardWidth boardHeight; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe insert a wait 1
here? As it is, I think it may do the instant
call multiple times in one tick, until it uses up its step allotment. It's not a big deal but I think it would be cleaner/more efficient to wait 1
before the recursive call.
304efde
to
517df26
Compare
See https://en.wikipedia.org/wiki/Lights_Out_(game)
The seed is not fixed; random valid games are generated and can be solved automatically via the provided solution.
One can use the solution strategy described here.