Prime Time Commented Source Code
Prime Time » Devlog
Commented, uncompressed code that describes the game logic and the techniques I used to reduce the size of the code. I used the shrinko8 tool to do the shrinking.
--ttj10 math puzzle
--by @dredds
-- define single-character
-- names for functions that
-- are used multiple times
g=mget
s=mset
m=mid
r=rnd
-- the number 15 is used in so
-- many expressions that it is
-- worth defining a single
-- character variable for it
f=15
-- the game state...
l={} -- positions of numbers
-- keyed by value
o=1 -- current objective.
-- this will be incremented
-- to 2 at the start of
-- the game loop
c=0 -- count of factors of the
-- current objective still
-- to be collected.
-- defined as zero so that
-- the first level, with
-- objective 2, is
-- initialised in the
-- iteration of the game
-- loop
a=1 -- is the player alive?
-- use 1/0 instead of
-- true/false so a can
-- be used in arithmetic
-- expressions without
-- conditional statements
x=4 -- player x coordinate
y=4 -- player y coordinate
-- the game loop repeats until
-- the player dies or reaches
-- the objective of 100
repeat
-- if the number of factors
-- to collect is zero, then
-- initialise the level. the
-- expression c<1 is one
-- character less than c==0,
-- and has the same effect
-- because the game sets c
-- to a positive integer and
-- decrements it by one every
-- time the player collects a
-- factor of the objective
if c<1 then
-- increase the objective.
-- o is initialised to 1 so
-- the first level has
-- objective 2 (the first
-- prime number)
o+=1
-- clear the map. the game
-- uses the map as a 2d array
-- to track what is in each
-- grid cell, so the map
-- must be cleared before
-- creating each level to
-- remove data about the
-- previous level
reload()
-- 1 in a map cell indicates
-- that it is the position of
-- the player
s(x,y,1)
-- for all numbers from 2
-- (the first prime) up to
-- the objective...
for n=2,o do
-- spawn a number only if n
-- is a prime. the string
-- of glyphs is a bitset
-- indicating which numbers
-- below 100 are prime.
-- the division and bit-
-- twiddling extracts the
-- bit corresponding to n
if ord(
"て(⌂き ⌂ (☉🐱⁸²²",
n\8+1
) & (1<<(n%8)) > 0
then
-- generate random coords
-- u and v for the number
u=r(f)\1v=r(f)\1
-- set the map cell u,v to
-- the value of the number
-- for collision detection
s(u,v,n)
-- add the coordinates to
-- the table of numbers
l[n]={x=u,y=v}
-- increase the count by
-- one if this is a prime
-- factor of the objective.
-- max defaults missing
-- parameters to zero, so
-- this is the same as
-- max(0,1-o%n). if n is
-- a factor of o, then o%n
-- is 0, 1-o%n is 1, and so
-- the statement increments
-- c. if not, then 1-0%n is
-- zero or negative, and
-- max clamps it to zero.
c+=max(1-o%n)
end
end
end
-- draw current state
-- clear the background to
-- black or dark blue,
-- depending on the current
-- level. this gives a clear
-- indication when the player
-- has a new objective
cls(o%2)
-- draw the objective in orange
-- cls resets the print state
-- so the objective is drawn
-- at the top-left
?o,9
-- draw the player character.
-- the print color persists
-- so the player is also drawn
-- in orange
?"웃",x*8,y*8
-- draw the numbers. iterating
-- with the hidden next
-- function is one character
-- shorter than iterating with
-- the pairs function.
-- numbers are drawn in green.
for n,e in next,l do
?n,e.x*8,e.y*8,3
end
flip()
-- only move the numbers if
-- there is any user input.
-- interpreting the input
-- uses some amazing code
-- by @pancelor that turns
-- the buttons bitset into
-- an angle.
b=btnp()*12\5/4
if b>0then
-- clear the old position of
-- the player in the map. mset
-- defaults the missing value
-- parameter to zero, saving
-- two characters.
s(x,y)
-- calculate the new position
-- of the player. the
-- positions are masked with
-- 0x0f, making them wrap
-- round the play area.
-- masking with f& at the
-- start of the expression
-- instead of &f at the end
-- means there does not need
-- to be a space between the
-- statement and the next,
-- saving two characters.
x=f&x+cos(b)
y=f&y+sin(b)
-- set the new position of
-- the player in the map
s(x,y,1)
-- for each number, using the
-- hidden next function again
-- to save a character
for n,e in next,l do
-- if the player is now at
-- the number's position,
-- check if the player has
-- collected a prime factor
-- or is dead
if g(e.x,e.y)==1 then
-- use the same trick with
-- max to calculate if the
-- number is a factor of
-- the objective (1) and
-- therefore the player is
-- still alive, or not (0)
-- and therefore it's game
-- over
a=max(1-o%n)
-- delete the number from
-- the table if it is a
-- prime factor, meaning
-- the player is still alive.
-- if the player is alive,
-- a == 1 so n*a == n.
-- if the player is not
-- alive a == 0 so n*a == 0
-- and this sets the unused
-- entry l[0] to nil.
--
-- an undefined variable is
-- used instead of the
-- keyword nil to save two
-- characters. (the shrinko8
-- tool replaces the name
-- undef with a single
-- character).
l[n*a]=undef
-- reduce the count of
-- prime factors to be
-- collected if n is a
-- prime factor
c-=a
else
-- if no collision with
-- the player, move the
-- number randomly. again,
-- the new coordinate is
-- masked with 15 to wrap
-- around the play area.
-- masking takes only two
-- characters. clamping
-- to 0..15 with the mid
-- function would take more.
-- again, putting f& at the
-- start of the expression
-- to eliminate the space
-- character after each
-- statement.
u=f&e.x+r(3)\1-1
v=f&e.y+r(3)\1-1
-- only move if the map at
-- u,v contains zero.
-- again, using <1 instead
-- of ==0 to save space.
if g(u,v)<1 then
-- clear the map at the
-- number's old position
s(e.x,e.y)
-- store the number in the
-- map at its new position
s(u,v,n)
-- store the new position
-- of the number
e.x=u
e.y=v
end
end
end
end
-- we keep doing that until
-- the player is not alive
-- (again using the <1 trick
-- to test for zero) or the
-- player has reached the
-- objective of 100, using
-- >99 instead of ==100 to
-- save two characters.
until a<1or o>99
-- if the player has one or
-- died, the game crashes.
-- no room for any game over
-- message. if the objective
-- was drawn as 100 during
-- the game loop, then the
-- player has won. if not,
-- the player has lost.
When shrunk, the code becomes…
u=mget i=mset b=mid h=rnd f=15l={}d=1a=0p=1e=4n=4repeat if a<1do d+=1reload()i(e,n,1)for e=2,d do if(ord("て(⌂き ⌂ (☉🐱⁸²²",e\8+1)&1<<e%8>0)o=h(f)\1r=h(f)\1i(o,r,e)l[e]={x=o,y=r}a+=max(1-d%e)
end end cls(d%2)?d,9
?"웃",e*8,n*8
for n,e in next,l do?n,e.x*8,e.y*8,3
end flip()s=btnp()*12\5/4if s>0do i(e,n)e=f&e+cos(s)n=f&n+sin(s)i(e,n,1)for n,e in next,l do if(u(e.x,e.y)==1)p=max(1-d%n)l[n*p]=c a-=p else o=f&e.x+h(3)\1-1r=f&e.y+h(3)\1-1if(u(o,r)<1)i(e.x,e.y)i(o,r,n)e.x=o e.y=r
end end until p<1or d>99
Leave a comment
Log in with itch.io to leave a comment.