Pizza and Beers
Fridays after work was when Dennis, Feynman and myself would take refuge in the savory and the cold that was pizza and beers. Amici’s in Soma, or Sliver in Berkeley if we were feeling adventurous.
I had become quite good with Apps Script, my PM Dennis, was obsessed with making internal tools with it. Almost asked him to shove it when he first asked me to code in Apps Script; but I came around because we all love Dennis.
Our CEO at the time, used to ask engineers in interviews, how they would code Tetris in Javascript.
During one particular pizza and beers session, when I was admitting my surprise at how good Apps Script is, I was challenged: “But can you code Tetris in it?” — a joke but, could I?
The answer is yes.
Sheet as a Datastore, sheet as a CSS grid
There are four major tasks to complete to have Tetris on Google Sheets:
- The falling of tetrominoes(that’s what tiles are called!)
- The stacking of tetrominoes
- The controlling of tetrominoes
- The rotating of tetrominoes
I decided to use one sheet as my frontend, like a CSS grid; one as my memory, holding the state of my application and another as my disk, holding information on tetrominoes and such.
It probably is possible and more confusing to merge the frontend and memory.
Falling
The simple part. Color some cells, sleep, color the cells below it and erase the ones above.
Stacking
We consult the memory while stacking: is there a tile below me?
To model a memory, I used a shadow board, another sheet with the same layout as the original board. It would remember where the tetrominoes stop and mark those cells with the number 1.
At each step of the tetrominoes are falling, they check to see if they should stack. They stack when there is another tetromino immediately below them. The layer below them is called the buffer. They know another tetromino has entered their buffer by checking the memory, where we keep a record of the has been.
Controlling
Another easy one. At each step, read the input, move the tetromino to left or right. I used w,a,s,d to remember my PC gaming days <3.
Rotating
The trick about rotating is that the buffer needs to change too:
Simple for just the straight tetromino. Adding the rest poses a challenge because each have their own shape and buffer requirements.
To address this, I used a coordinate system. I put each tetromino in a 3×3 block, and referenced their cells and buffer cells, using the middle cell of the 3×3 block as origin.
Every origin on column C belongs to 0 degrees rotation, column G 90 degrees and so on. I is on row 3, J on 7, L on 11 and so on.
Then, using a map, for S for instance, we have:
...
's':{0:[[left, up, ur], [ll, down, right]], 90:[[up, right, lr], [down, d2r]], 180:[[left, up, ur], [ll, down, right]], 270:[[up, right, lr], [down, d2r]]},
...
Let’s open one up, 0:
{0:[[left, up, ur], [ll, down, right]] ...
The first array says for a 0 rotated S, excluding the origin, the cells to the left, up and upper left of the origin are colored.
The second array says for a 0 rotated S, the buffers are at lower left, down and right of the origin.
You can see the rest here if interested.
The Final Product
Added some animation for that sweet dopamine spike.
Answer to bug challenge
There actually must be buffers to the left and right of the tetrominoes too, otherwise they will exit the bounds or bleed into other tetrominoes laterally. Even though my drop cycle makes it hard to do so.
Social
Follow me on twitter
Appendix
Code: https://github.com/maininformer/Tetris/tree/master
Sheet:https://drive.google.com/drive/folders/1X_aPHyIAqY5bI9Dtc5oTLLBRxVCovXzG
Leave a reply to plumSemPy Cancel reply