# TweetTweetJam

Hosted by eggnog · #TweetTweetJam

# I would love to see the unobfuscated code for these projects

A topic by nextlevelbanana created Nov 14, 2018 Views: 174 Replies: 10
Viewing posts 1 to 9

I want to understand your wizardry! Anyone willing to share?

HostSubmitted(+1)

I'd be willing, but I wrote the code as obfuscated in the first place, since I knew I'd have to shorten it later! Perhaps I'll unobfuscate one of my games tonight for this thread!

Sure. Here's the original code for Patrick's Picochallenge:

```poke(24364,3)x="웃"v="▥"h="▤"b={}for i=1,36 do b[i]=i%9<2 and""or"█"end for i in all{"⬆️","➡️",h,"⬅️","⬇️",v,x}do repeat f=1+flr(rnd(36))until b[f]!=""b[f]=i
if(i==x)p=f
end::_::t=btnp cls()for i=0,35 do
k=b[i+1]
?k,i%9*8,6*flr(i/9)+20,k==x and 11 or 7
end b[p]=""q=p
if(t(0))q-=1
if(t(1))q+=1
if(t(2))q-=9
if(t(3))q+=9
if(b[q]and#b[q]>0)p=q t=b[p]
if(t=="⬆️"or t==v)b[p-10]=""b[p-9]=""b[p-8]=""
if(t=="⬇️"or t==v)b[p+10]=""b[p+9]=""b[p+8]=""
if(t=="⬅️"or t==h)b[p-10]=""b[p-1]=""b[p+8]=""
if(t=="➡️"or t==h)b[p+10]=""b[p+1]=""b[p-8]=""
b[p]=x flip()goto _```

My attempt at unobfuscating and commenting it (I wrote it minified from the start):

```--patrick's picochallenge
--by tobiasvl
--use 64x64 resolution
poke(0x5f2c,3)
--generate a blank board of
--empty █ tiles
board={}
--the board is 7x4, but we
--represent it as a one-
--dimensional table. we also
--represent it as 36 tiles, ie
--a 9x4 grid, with two columns
--of "" on each end, so ⬅️➡️▤▥
--tiles don't wrap around when
for i=1,36 do
if i%9<2 then
--first and last column
board[i]=""
else
board[i]="█"
end
end
--populate the board with tiles
--and the player's starting tile
tiles={"⬆️","➡️","▤","⬅️","⬇️","▥","웃"}
for i in all(tiles) do
--find a random tile which is
--not in the "invisible" outer
--columns
repeat
position=1+flr(rnd(36))
until board[position]!=""
board[position]=i
--remember the player
if (i=="웃") player=position
end
--game loop
::_::
cls()
--print the board
--here's the only obfuscation i
--left in: here i loop from
--0 to 35, instead of 1 to 36,
--because then i only need to
--do i+1 once instead of i-1
--twice.
for i=0,35 do
local tile=board[i+1]
--the player is green
if tile=="웃" then
color(11)
else
color(7)
end
--properly centering the board
--takes up too many characters
--so just an approximation
print(tile,i%9*8,6*flr(i/9)+20)
end
--erase the player character
--and destroy the tile
board[player]=""
--remember the player's position
new_player=player
--move the player's position if
--an arrow key is pressed
if (btnp(⬅️)) new_player-=1
if (btnp(➡️)) new_player+=1
if (btnp(⬆️)) new_player-=9
if (btnp(⬇️)) new_player+=9
--if we're still inside the
--board proper, ie the tile isn't
--nil (outside the board) or ""
--(the border columns), make
--that the new position.
if board[new_player] and board[new_player]!="" then
player=new_player
tile=board[player]
end
--if the player lands on one of
--the special tiles, destroy
if tile=="⬆️" or tile=="▥" then
--destroy three tiles above
board[player-10]=""
board[player-9]=""
board[player-8]=""
end
if tile=="⬇️" or tile=="▥" then
--destroy three tiles below
board[player+10]=""
board[player+9]=""
board[player+8]=""
end
if tile=="⬅️" or tile=="▤" then
--destroy three tiles left
board[player-10]=""
board[player-1]=""
board[player+8]=""
end
if tile=="➡️" or tile=="▤" then
--destroy three tiles right
board[player+10]=""
board[player+1]=""
board[player-8]=""
end
--put the player in the new
--(or old!) position
board[player]="웃"
--loop
flip()
goto _
```

Fun exercise. I actually found a bug while looking through it, so thanks for that!

The game itself is a demake of a game I made earlier this year, so it was really interesting to try to find smarter solutions than I did originally.

Edit: itch stripped out blank lines from the code for some reason, here's a gist.

Submitted (3 edits)

Here's Froggy Road, de-obfuscated!  I tried to make the variable names more clear and removed all the line-break-saving measures, but I didn't change any of the logic, so there are still some spots where it does a weird thing to avoid an if statement or whatever (for example, every road-lane draws a frog, but they're all hidden offscreen except for the lane which actually-currently-contains the player).

(edit - like with tobiasvl, my linebreaks get stripped here - here's a version on pastebin which keeps them intact)

```frogX=0
frogY=0
died=0
camX=frogX
camY=frogY
::_::
flip()
cls(1)
// weird arrow key input
z=btnp()
// add +/- 5 to x for right/left arrows
frogX+=(flr(z/2)%2-z%2)*5
// add +/- 1 to y for up/down arrows
frogY-=flr(z/8)%2-flr(z/4)%2
// camera eases toward frog position
camX+=(frogX-camX)/3
camY+=(frogY-camY)/3
for laneY=frogY+25,frogY-2,-1 do
// each lane has its own randomized properties
srand(laneY)
// car animation properties
cycleOffset=rnd()
carSpeed=8+rnd(16)
// perspective distortion strength
// (persp=0 means "infinitely far away")
persp=(laneY-camY+2.3)/12

// (but draw it offscreen if persp<0)
rectfill(-1,64+9/persp,sgn(persp)*127,127,6-laneY%2)
// draw a frog in every lane...
// but offset it off the screen if the
// frog isn't actually in this lane
print("🐱",61+(frogX-camX)/persp+(laneY-frogY)*99,62+7.5/persp,3)
// each lane has a different # of cars
// (early/negative lanes have no cars)
for i=1,sgn(laneY-2)*rnd(8) do
// a car has two halves, parallel to the lane
// (near-half and far-half)
for k=0,1 do
// each car has five sub-circles for the body
for j=-2,2 do
// x-position of this sub-circle
worldX=(i*carSpeed*4+j+t()*carSpeed+cycleOffset-camX)%198-99

// collision detection for the frog
if laneY==frogY and abs(worldX-frogX+camX)<2 then
died=1
end
// far-half of car uses a different persp value
persp2=persp-k/60
// get screen position of this sub-circle
screenX=worldX/persp2+64
screenY=5/persp2+64
// draw this sub-circle
circfill(screenX,screenY,2/persp2,laneY%5)
// draw a wheel, but only if j equals +/- 2
circfill(screenX,screenY+2/persp2,(abs(j)-1)/persp2,0)
end
end
end
end
// self-explanatory death check
if (died>0) then
end
// if you're not dead, continue the game loop
goto _
// you done goofed
// random red/orange noise
pset(rnd(128),rnd(128),8+rnd(2))
// death UI
print("❎ reset",46,62,7)
print("score: "..frogY,3,3)
// restart command
if btn(5) then
run()
end
// haven't reset yet. resume death
```

And then just for the sake of easy comparison, here's the original code:

```x=0y=0l=0q=x
r=y
f=rnd
g=flr
h=circfill::_::flip()cls(1)z=btnp()x+=(g(z/2)%2-z%2)*5y-=g(z/8)%2-g(z/4)%2
q+=(x-q)/3r+=(y-r)/3
for z=y+25,y-2,-1 do
srand(z)o=f()m=8+f(16)p=(z-r+2.3)/12rectfill(-1,64+9/p,sgn(p)*127,127,6-z%2)
?"🐱",61+(x-q)/p+(z-y)*99,62+7.5/p,3
for i=1,sgn(z-2)*f(8)do
for k=0,1 do
for j=-2,2 do
u=(i*m*4+j+t()*m+o-q)%198-99
if(z==y and abs(u-x+q)<2)l=1
v=p-k/60n=u/v+64w=5/v+64h(n,w,2/v,z%5)h(n,w+2/v,(abs(j)-1)/v,0)end
end
end
end
if(l>0)goto d
goto _::d::pset(f(128),f(128),8+f(2))
?"❎ reset",46,62,7
?"score: "..y,3,3
if(btn(5))run()
goto d
```

I just put my earlier tweetgame on Itch.io and included fully commented source code. You can see it here: https://kometbomb.itch.io/breakout-280

How did you format the source code there?

I used hilite.me but the wysiwyg HTML editor is really annoying with custom HTML (especially if you edit it later).

I de-obfuscated my code for Putt, in case anybody is interested. Planning to make this into a proper lil PicoPutt game, but gonna need to spend a LOT of time polishing it.

function _init()
spawn_level()
end

function _update()
move_player()
end

function _draw()
cls()
draw_bg()
collision()
draw_player()
end

-- levelgen

function spawn_level()
grass={}
sand={}
for i=1,5 do
j=14+i*16
k=50+rnd(35)
q=17+rnd(10)
-- make grass and sand
if i>1 and
i<5 then
end
-- make player and hole
if i==1 then
p={x=j-q/2,y=k,a=0,xd=0,yd=4,p=1,v=0}
elseif i==5 then
h={x=j+q/2,y=k}
end
end
end

-- draw functions

function draw_bg()
for v in all(grass) do
circfill(v.x,v.y,v.r,11)
end
for v in all(sand) do
circfill(v.x,v.y,v.r,4)
end
-- hole
circfill(h.x,h.y,2,0)
--    power bar
circfill(64,8,5,7)
print(p.p,63,6,0) end

-- player

function draw_player()
circfill(p.x,p.y,2,7)
circfill(p.x+p.xd,p.y+p.yd,0)
end

function move_player()
-- set angle of shot
if btnp(5) then
if p.a<6.28 then
p.a+=.1 else p.a=0
end
p.xd=sin(p.a)*4
p.yd=cos(p.a)*4
end
-- set shot power
if btnp(2) then
if p.p<5 then
p.p+=1 else
p.p=1
end
end
-- shoot
if btnp(4) then
p.v=p.p
end
-- move ball, apply deceleration
p.x+=p.v*p.xd
p.y+=p.v*p.yd
p.v*=.7
end

function collision()
-- hole/border pixel collision
if pget(p.x,p.y)==0 then
_init()
end
-- sand trap collision
if pget(p.x,p.y)==4 then
p.v/=3
end
end

And here's the obfuscated code:

::z::e={}f={}
d,xd,yd,p,s,b,t,o=0,0,4,1,0,circfill,btnp,rnd
for i=1,5 do
if(i==1)x,y=j-q/2,k
if(i==5)w,u=j+q/2,k
end::_::cls()if t(5) then
if(d<6.28)d+=.1else d=0
xd=sin(d)*4
yd=cos(d)*4
end
if t(2) then
if(p<5)p+=1else p=1
end
if(t(4))s=p
x+=s*xd y+=s*yd s*=.7
for v in all(e) do
b(v.x,v.y,v.r,11)end
for v in all(f) do
b(v.x,v.y,v.r,4)end
b(w,u,2,0)
if(pget(x,y)==0)goto z
if(pget(x,y)==4)s/=3
b(x,y,2,7)b(64,8)b(x+xd,y+yd,0)
?p,63,6,0
flip()goto _

Here's my other game too, Lights Out. I'm more pleased with this game as it has two modes, a title screen and a win state.

Minified:

```z="lights out"poke(24364,3)::x::flip()cls()k=btnp()w={[0]="","▒","█"}f=flr
?z,12,18,stat(95)%4
?"z: classic\nx: 2000",12,32,7
if(k<9)goto x
if(k>16)w[3]="█"
b={}p=2m=0
for i=1,35 do
b[i]=i%7<2 and 0or 2
end::_::flip()cls()
?m,30,54
for i=1,35 do
j=b[i]
?w[j],i%7*8-2,6*f(i/7)+18,j*3+2
end
x=p%7*8-2y=6*f(p/7)+17rect(x-1,y,x+7,y+6,9)q=0k=btnp()h={-1,1,-7,0,7}if k>9then m+=1for i in all(h)do
o=b[p+i]
if(o and o>0)b[p+i]=o%#w+1
end
elseif k>0then q=h[f(k/2)+1]end
g=b[p+q]
if(g and g>0)p=p+q
for i=1,35 do
if(b[i]>1)goto _ end
z="you win!"goto x
```

Unobfuscated and commented (gist, since itch strips linebreaks):

```-- title screen logo
title="lights out"
-- 64x64 resolution
poke(0x5f2c,3)
-- title screen loop
::title_screen::
-- clear screen
-- (we do it here because we
-- jump back upon winning)
flip()
cls()
key=btnp()
-- light values and visuals:
-- 0: no light
-- 1: light off
-- 2: red light
-- 3: green light
-- (green light only in mode
-- "lights out 2000")
lights={[0]="","▒","█"}
-- print title with color
-- alternating based on time
-- (stat(95) is current second)
print(title,12,18,stat(95)%4)
print("z: classic\nx: 2000",12,32,7)
-- if the button value is below
-- 16 (all values are powers of
-- two so by checking below 9
-- here we save a character),
-- including 0 (no input), we
-- just loop. 16 is the z key,
-- so if that's the case we
-- will fall through to classic
-- mode.
if (key<9) goto title_screen
-- button value 32 is x, so in
-- that case we add the green
-- light value for "2000 mode".
if (key>16) lights[3]="█"
-- initialize the board
board={}
-- start in the left corner
player=2
-- move counter
moves=0
-- initialize the 5x5 board
-- with the value 2 (red light)
-- but add a column of 0 (no
-- light) on either side to
-- avoid wrapping when toggling
for i=1,35 do
-- if column is 1 or 7:
if i%7<2 then
board[i]=0
else
board[i]=2
end
end
-- gameplay loop
::play::
flip()
cls()
-- move counter
print(moves,30,54)
-- print the board
for i=1,35 do
light=board[i]
-- a trick: each light's
-- color can be computed from
-- its value
-- none: 0*3+2 = 0 (black)
-- off: 1*3+2 = 5 (dark gray)
-- red: 2*3+2 = 8
-- green: 3*3+2 = 11
light_color=light*3+2
-- print lights in grid
print(lights[light],i%7*8-2,6*flr(i/7)+18,light_color)
end
-- print the player's marker
x=player%7*8-2
y=6*flr(player/7)+17
rect(x-1,y,x+7,y+6,9)
-- marker movement: we find the
-- new position and see if it's
-- valid. if so, we move it.
new_player=0
key=btnp()
-- used for movement and for
-- toggling lights. notice that
-- 0 (ie. no movement, the
-- currently marked light) is
-- in position 4 in the table.
-- this is a trick, used when
-- mapping input keys to
-- positions.
directions={-1,1,-7,0,7}
-- if the key is x or z (value
-- is 16 or 32) we toggle:
if key>9 then
moves+=1
-- lights in all directions
for i in all(directions) do
light=board[player+i]
-- if it's inside the board
if light and light>0 then
-- cycle light value up
-- (use #lights here so
-- we cover both classic
-- and 2000 mode)
board[player+i]=light%#lights+1
end
end
-- if the key is an arrow key
-- (value is 1, 2, 4 or 8):
elseif key>0 then
-- divide the button value by
-- two and add 1 and we get
-- 1, 2, 3 or 5. look that up
-- in the directions table
-- (recall that position 4
-- was the current light)
new_player=directions[flr(key/2)+1]
-- if it's inside the board
light=board[player+new_player]
if light and light>0 then
-- move there
player=player+new_player
end
end
-- if any of the lights are
-- still on, stay in the
-- gameplay loop
for i=1,35 do
if (board[i]>1) goto play
end
-- otherwise, set the title to
-- a congratulatory message
title="you win!"
-- and go back to the title
-- screen
goto title_screen
```

Sorry for the late reply, just saw this now! Here's some commented code for Ninja Punch Zone. It's been long enough that I had to go through it and figure out what every line did again, and while doing that I found a couple of things I think I can optimize further. So thanks for that! :D

EDIT: Itch's comment system mangles the formatting so I've put an easier-to-read version up here.

```--INITIALIZING VARIABLES--
--the number '30' came up a lot in the math stuff bleow,
--so i assigned it to a variable to save characters
t=30
--the player's x position
x=t
--the player's FIST position, relative to the player
--(it's always four pixels away from the player in the direction they're facing,
--but storing the offset in a variable saves chars when drawing later on)
f=4
--making aliases for some commonly used functions to save chars later on
z=rectfill
y=rnd
a=abs
--cooldown timer for the player's punch
c=0
--x position of red ninjas coming in from the right/left respectively
--every time we do this we randomize their position slightly,
--so the ninjas always come at the player at different times
r=130+y(30)
l=y(30)-82
--the player's score and the high score
s=0
h=0
--changing to low res mode (64x64 resolution)
poke(0x5f2c,3)
--the UPDATE LOOP--
function _update60()
--if the player presses left or right then move them in that direction
if btn(⬅️)
then x=max(x-1,3)
f=-4
end
if btn(➡️)then
x=min(x+1,62)
f=4 end
end
--if the player presses 'O' then punch,
--but only if the cooldown timer from the last punch is finished
if c==0 then
if(btnp(🅾️)) c=10
end
--updating the cooldown timer for this frame
c=max(c-1,0)
--moving the two red ninjas towards the player
l+=.7
r-=.7
--if the left ninja has run all the way off screen then reset them
--also: some more character optimization seems possible here!
--must have missed it at the time :-D
if l>70 then
l=y(t)-t
end
-- likewise, if the right ninja has ran all the way off the screen then reset them
if(r<-10) r=y(t)+70
--ALSO: ^^^^ do i even need to check for the ninjas running off screen?
--they should collide with the player and reset before they reach the other side.
--going to look into this, I might be able to create an even more optimized version! \o/
--PUNCH CHECKING. if the punch cooldown is greater than zero,
--then check if the player's arm is close enough to an enemy ninja to hit them
--if it is then we add one to the score and reset the ninja's position off-screen
if c>0 then
if a(x-l+f)<4 then
s+=1l=y(t)-t
end
if a(x-r+f)<4 then
s+=1r=y(t)+70
end
end
-- if the player has beaten the high score then we update the hi-score
if(s>h) h=s
-- if the player has collided with either of the two ninjas
-- we start a new game (reset the score and move the two ninjas to their start points)
if a(x-r)<2or a(x-l)<2 then
s=0
r=y(t)+130
l=y(t)-82
end
-- finally, the DRAW LOOP--
-- (naughtily done in _update60() to save chars)
-- clear the screen
cls()
--draw two rectangles for the ground and sky
z(0,14,64,49,12)
z(0,43,64,49,5)
--draw the player
?"웃",x-4,39,0
--if the player is punching, draw a "-" for the player's extended arm
if c>0 then
?"-",x+f-2,39,0
end
--draw the two red ninjas
?"웃",l-3,39,8
?"웃",r-3,39,8
--print the score and high score at the top
?s,6,16,10
?h,54,16,10
end```