# Tiling, given vertex configuration

The task is to tile polygons, given a vertex configuration.

Scoring

Your score is equal to the "complexity level" your submission reaches. Complexity levels are cumulative, meaning that to reach #3 you must also support #1 & #2.

Submissions at an equal complexity level are distinguished by byte count; lowest wins.

Input

Input is a string containing a vertex configuration, representing a vertex figure. That is, a dot separated list of integers, where each integer (n) represents a regular n-gon, connected by a common vertex.

The following vertex configurations must be supported:

• 3.3.3.3.3.3
• 3.3.3.3.6
• 3.3.3.4.4 (note that order is reflected in the vertex figure, therefore the below does differ)
• 3.3.4.3.4
• 3.12.12
• 3.4.6.4
• 3.6.3.6
• 4.4.4.4
• 4.6.12
• 4.8.8
• 6.6.6

Output - Complexity Level #1: Vertex Figure

At this complexity level, output is an image showing the vertex figure corresponding to the given input.

Input is prepended with an F to signify that the vertex figure should be output, and not the full tiling.

For example F3.6.3.6 gives this vertex figure:

Output - Complexity Level #2: Tiling

At this complexity level output is an image showing a uniform tiling using the vertex figure corresponding to the given input.

For example 3.6.3.6 gives this tiling:

There are no restrictions on colour or format (barring loopholes).

Output - Complexity Level #3: Dual Tiling

At this complexity level a 'dual tiling' can be formed from each tiling. This is achieved by drawing lines from the centre of each polygon to the centre of each bordering polygon.

Dual tiling is specified by prepending input with a V.

For example V3.6.3.6 gives this dual tiling (in red):

• Some of these tilings have synonyms. For example the following are all the same: 3.3.3.4.4 3.3.4.4.3 3.4.4.3.3 4.4.3.3.3 4.3.3.3.4. Do we have to support all synonyms, or just the lexically lowest one (as given in the question)? Also, 3.3.3.3.6 exists in two mirror image forms. I understand either is acceptable. – Level River St Nov 12 '14 at 22:24
• The page you linked does not match the list given. 3.3.3.4.4 is missing for example. en.wikipedia.org/wiki/… matches your list exactly. I understand outline or filled polygons are acceptable (or a combination of the two?) Some duals are already in the list. For example 4.4.4.4 is its own dual and 3.3.3.3.3.3 and 6.6.6 are mutally dual. As the duals are displayed independently of their parents, I understand there is no need for correct alignment with the parent. – Level River St Nov 13 '14 at 0:23
• you must support input as it appears in the list - you may support synonyms but you don't have to - you must support all duals, even self-duals. – jsh Nov 13 '14 at 9:30
• outline/filled - fine either way. any styling is allowed besides loopholes (make everything white, make drawing area tiny etc.). alignment not required. I could tell you you're not allowed to use one reflection of 3.3.3.3.6 but how would you know which one it is? :) – jsh Nov 13 '14 at 9:37
• Now you've changed the scoring, what is the tie-break? Is that still shortest code? If so, do the vertex configurations have to be delimited by dots or can we choose another symbol like comma or space? – Level River St Nov 14 '14 at 4:37

# BBC BASIC

Rev 1 Golfed code, 655 ASCII characters, tokenised filesize 614

Some major improvements to the data table, by hashing the string A.B..N to a number (1*A+2*B+..n*N)+n before looking up, and by storing only one translation vector (the other one is generated by code.) More explanation when I have finished golfing.

t=PI*2DIMm(9)
c=0z=0INPUTz$FORi=1TOLEN(z$)d%=VAL(MID$(z$,i))IFd%c+=1m(c)=d%i-=d%=12z+=c*d%
UNTILl=z+c
l=4-3*(m(3)MOD3=0)-8*(l=59)
DATA69,0,70,65,100,35,66,149,0,49,109,0,52,80,0,55,0,189,39,120,0,44,40,40,58,55,95,47,136,0,59,40,0
VDU23,23,3|
FORr=-9TO19FORs=-9TO9a=1+e*(r*2+s)-f*l*s/4b=1+f*(r*2+s)+e*l*s/4p=40q=0FORk=1TOm(c)/2FORj=1TOc
n=m(j)o=TAN(PI/3)IFe=109ANDn<>4o=1
w=-p*COS(t/n)-q*SIN(t/n)q=p*SIN(t/n)-q*COS(t/n)p=w
u=p:v=q
x=a:y=b
MOVEx,y
FORi=1TO14x+=u*2y+=v*2IFVAL(z$)DRAWx,y ELSEGCOL9LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n) w=v*COS(t/n)-u*SIN(t/n)u=v*SIN(t/n)+u*COS(t/n)v=w NEXTNEXT p=u:q=v a=x:b=y NEXTNEXTNEXT  Rev 0 Golfed code, 770 ASCII characters, tokenised filesize 728 All I've done here is remove comments, unnecessary whitespace and quote marks, and put all the DATA on one line. There's certainly room for more golfing. t=PI*2DIMm(9) c=0INPUTz$
FORi=1TOLEN(z$)d%=VAL(MID$(z$,i))IFd%c+=1:m(c)=d%:i-=d%=12 NEXTREPEATREADl$,e,f,g,h
UNTILMID$(z$,1-(VAL(z$)=0))=l$
DATA3.3.3.3.3.3,240,0,120,70,3.3.3.3.6,200,70,40,210,3.3.3.4.4,80,0,40,150,3.3.4.3.4,-40,150,150,40,3.12.12,300,0,150,260,3.4.6.4,220,0,110,188,3.6.3.6,160,0,80,140,4.4.4.4,80,0,0,80,4.6.12,0,380,330,-190,4.8.8,272,0,136,136,6.6.6,240,0,120,70
VDU23,23,3|
FORr=-9TO19 FORs=0TO9a=1+e*r+g*s
b=1+f*r+h*s
p=40q=0FORk=1TOm(c)/2FORj=1TOc
n=m(j)o=TAN(PI/3):IFe=220ANDn<>4o=1
w=-p*COS(t/n)-q*SIN(t/n)q=p*SIN(t/n)-q*COS(t/n)p=w
u=p:v=q
x=a:y=b
MOVEx,y
FORi=1TO14x+=u*2y+=v*2IFVAL(z$)DRAWx,y ELSEGCOL9LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n) w=v*COS(t/n)-u*SIN(t/n)u=v*SIN(t/n)+u*COS(t/n)v=w NEXTNEXT p=u:q=v a=x:b=y NEXTNEXTNEXT  Explanation This is a continuation of my previous Level 1 answer, but I decided to post it separately because it's rather long. Level 2 This is achieved by translation of my "level 1.5" templates from my previous answer. The two translation vectors for each tiling are hardcoded. I take advantage of the fact that an isosceles triangle of base 80 and height 70 is a very good approximation of an equilateral triangle, and a right triangle with hypotenuse vector (56,56) has a hypotenuse length very close to 80. Level 3 To plot the duals, instead of plotting an edge of the polygon, we plot a spoke from the middle of that edge to the centre of the polygon. This is at right angles to the edge and has length of 1/TAN/(PI/n) times of the vector (u,v) which in turn is half as long as the edge. Unfortunately, because certain polygons in tilings 3.3.3.3.6 and 3.4.6.4 are not plotted explicitly, they would not be plotted if we only did this. Therefore the spoke also extends outward from the polygon. The outward extension is controlled by the variable o. By default the extension is sufficient to reach the centre of a triangle, but for 3.4.6.4 it needs to be extended more in order to draw the duals of the squares that are not plotted explicitly. So enough extension to fill in the missing squares is applied when hexagons and triangles are plotted explicitly, but the normal extension is applied when squares are plotted explicitly, to avoid spurious lines in the adjacent triangles. Here's what they look like without the spoke extensions. The holes in the dual pattern can be clearly seen. The correct output can be seen in the main picture at the bottom of the answer Commented Code Differences from my previous answer are indicated inline  t=PI*2 :REM constant Tau = PI*2 DIMm(9) :REM declare array for the numbers in the input c=0 :REM number of polygons in the list INPUTz$
FORi=1TOLEN(z$) :REM for each character in the input d%=VAL(MID$(z$,i)) :REM use VAL to return the numeric value of the substring to the right and store to integer variable IF d% c+=1 :m(c)=d%: i-=d%=12 :REM if the last character read was a number, d% contains it, otherwise 0. Advance c and store to m. If it is 12, increment i to skip a character. NEXT REM BLOCK OF NEW CODE to define vectors (e,f) and (g,h) for each possible tiling REPEAT READ l$,e,f,g,h                               :REM read an entire line of the data below
UNTIL MID$(z$,1-(VAL(z$)=0))=l$                 :REM abort the loop when l$coincides with the input. the MID$ strips off the 'V' from the input where necessary.

DATA"3.3.3.3.3.3",240,0,120,70
DATA"3.3.3.3.6",200,70,40,210
DATA"3.3.3.4.4",80,0,40,150
DATA"3.3.4.3.4",-40,150,150,40
DATA"3.12.12",300,0,150,260
DATA"3.4.6.4",220,0,110,188
DATA"3.6.3.6",160,0,80,140
DATA"4.4.4.4",80,0,0,80
DATA"4.6.12",0,380,330,-190
DATA"4.8.8",272,0,136,136
DATA"6.6.6",240,0,120,70

VDU23,23,3|                                           :REM change linewidth to 3 (default is 1)

REM END BLOCK OF NEW CODE

FORr=-9TO19 FORs=0TO9                                 :REM two new loops for translations

a=1+e*r+g*s                                       :REM modified code for
b=1+f*r+h*s                                       :REM coordinates to start drawing at

p=40:q=0                                          :REM vector of first line

FORk=1TOm(c)/2                                    :REM draw half as many vertex figures as there are sides on the last polygon in the list

FORj=1TOc                                       :REM for each polygon on the list
n=m(j)                                        :REM n=number of sides
o=TAN(PI/3): IF e=220 AND n<>4 o=1            :REM new code for the spoke extension 1/o.

w=-p*COS(t/n)-q*SIN(t/n)                      :REM rotate the starting vector anticlockwise by the internal angle of the current polygon
q=p*SIN(t/n)-q*COS(t/n)                       :REM to avoid overlapping the previous one, if any.
p=w

u=p:v=q                                       :REM make a local copy of the vector and coordinates
x=a:y=b                                       :REM to avoid corruption of p,q,a,b during the drawing of the polygon
MOVE x,y                                      :REM move the graphics cursor to the start without drawing
FORi=1TO14                                    :REM do 14 iterations regardless of the number of sides on the polygon
x+=u*2                                      :REM increment x and y by the vector representing the side
y+=v*2                                      :REM the value is double (u,v) to facilitate drawing duals later

REM if z$begins with a numeric character, draw an edge. If not, change to red and draw a spoke. IFVAL(z$) DRAW x,y ELSE GCOL9: LINEx-u-v/o,y-v+u/o,x-u+v/TAN(PI/n),y-v-u/TAN(PI/n)

w=v*COS(t/n)-u*SIN(t/n)                     :REM rotate the vector clockwise
u=v*SIN(t/n)+u*COS(t/n)                     :REM through the external angle of the polygon
v=w
NEXT                                          :REM draw next edge of the current polygon
NEXT                                            :REM draw next polygon of the current vertex

p=u:q=v                                         :REM once the vertex is finished, we will be two sides around the perimeter of the last polygon.
a=x:b=y                                         :REM copy the position and direction data into p,q,a,b.
NEXT                                              :REM draw next vertex figure

NEXT                                                :REM close the two new translation loops
NEXT


Output

The program performs only one tiling or dual for each run. However it plots the duals in red. To save space, I ran the program twice without clearing the screen in order to superimpose the dual on top of the regular tiling.

# Mathematica

Level 1 contains the basic tile templates that are repeatedly stamped to tile a plane.

Level 2 does the tiling.

There are still 2 tilings I haven't been able to achieve. They appear to require rotation as well as translation.

## Level 1: Vertex Figure (559 bytes)

nGon[n_]:=
{ColorData[46,"ColorList"][[n]],Polygon@Switch[n,
3,{{0,0},{-1/2,.866},{-1,0},{0,0}},
4,{{0,0},{0,1},{-1,1},{-1,0},{0,0}},
6,Table[{Cos[i 2Pi/n],Sin[i 2Pi/n]}+{-.5,.866},{i,0,n}],
8,Table[1.31{Cos[i Pi/4],Sin[i Pi/4]}+{-0.5,1.207},{i,1/2,9}],
_,Table[2{Cos[i 2Pi/n],Sin[i 2Pi/n]}+{-0.5176,1.932},{i,1/2,13}]]}
innerAngle[n_]:=180-360/n
g[{}]=0;
g[a_]:=-(Plus@@innerAngle/@a)

h[{{},__,out_}]:=out
h[{list_,angles_,out_}]:=(
z=GeometricTransformation[nGon[l=list[[1]]],RotationTransform[g[angles] Degree]];
h[{Rest@list,Append[angles,l],Append[out,z]}])


Testing

Row[Graphics[{EdgeForm[{Blue}], #},
ImageSize -> 70] & @@ {h[{#, {}, {}}]} & /@ {{3, 3, 3, 3, 3,
3}, {3, 3, 3, 3, 6}, {3, 3, 3, 4, 4}, {3, 3, 4, 3, 4}, {3, 12,
12}, {3, 4, 6, 4}, {3, 6, 3, 6}, {4, 4, 4, 4}, {4, 6, 12}, {4, 8,
8}, {6, 6, 6}}]


## Level 2: Tiling (690 additional bytes)

The rules return tiling offsets and indents for each configuration.

r is the basic function that outputs the tilings.

p shows the template and the respective tiling. White spaces correspond to those not covered by the template.

rules={
{3,6,3,6}-> {2,3.47,0,0},
{4,4,4,4}-> {1,1,0,0},
{6,6,6}-> {3,2.6,1.5,0},
{3,3,3,3,3,3}-> {1.5,1.74,0,.9},
{3,3,3,3,6}-> {2,2.6,-0.4,1.8},

{4,6,12}->{4.2,4.9,0,2.5},
{3,3,4,3,4}-> {1.87,1.86,-.5,-0.5},
{4,8,8}-> {3.4,3.4,0,0},
{3,3,3,4,4}-> {2,1.87,.52,0},
{3,12,12}-> {3.82,6.73,0,0},
{3,4,6,4}-> {1.4,4.3,0(*1.375*)-1,-2.4}};

r[nGons_]:=
Module[{horizHop,vertHop,indent,downIndent},
{horizHop,vertHop,indent,downIndent}=(nGons/.rules);
Graphics[{EdgeForm[{Blue}],Table[GeometricTransformation[h[{#,{},{}}]&/@{nGons},
TranslationTransform[{
If[MemberQ[{{3,3,4,3,4},{3,3,3,3,6},{3,4,6,4}},nGons],indent *row,indent Boole[OddQ[row]]]+col horizHop,
If[MemberQ[{{3,3,4,3,4},{3,3,3,3,6},{3,4,6,4}},nGons],downIndent *col,downIndent Boole[OddQ[col]]]-row vertHop}]],
{col,0,5},{row,0,4}]},ImageSize-> 250]]

p[nGon_]:=Row[{Graphics[{EdgeForm[{Blue}],h[{nGon,{},{}}]},ImageSize->70],r@nGon}];


Testing

Triangular tiling

p[{3, 3, 3, 3, 3, 3}]


hexagonal

p[{6, 6, 6}]


square

p[{4, 4, 4, 4}]


unknown

p[{3, 3, 4, 3, 4}]


truncated square

p[{4, 8, 8}]


trihexagonal

p[{3, 6, 3, 6}]


truncated hexagonal

p[{3, 12, 12}]


unnamed

p[{3, 3, 3, 3, 6}]


elongated triangular

p[{3, 3, 3, 4, 4}]


Tilings to figure out

• I'm pretty much at the same stage as you. I can create the tiles, but working out the tiling is going to take a bit. The wiki steveverill posted in his comments sort of makes it looks like various schemes made need to be supported. Need to do a bit of study:) – MickyT Nov 14 '14 at 1:35
• Micky, The vertical and horizontal displacement of a tile will depend on the row no., the col no. using offsets unique to the case at hand. I'm working them out one by one and will later generalize. – DavidC Nov 14 '14 at 2:31
• @DavidCarraher great start. I have made a change to the scoring criteria that may affect you. – jsh Nov 14 '14 at 3:09
• Good so far! If you reduce your horizontal translation on 3.3.3.3.3.3 by half, so that the units overlap, you can get rid of those diamonds and fix that tiling. You still have more to do on 3.3.3.3.6,3.4.6.4 and 4.6.12 though. – Level River St Nov 16 '14 at 23:29
• Re 4.6.12 anyone know what it should look like? - All the required tilings are at en.wikipedia.org/wiki/… . See my comment on the question. This is a different page to the one mentioned in the question. But 4.6.12 is also shown on that page anyway. – Level River St Nov 17 '14 at 0:19

## R

Step #1

Here's my effort at building the tiles. Tiling to come next. This does not validate the input, so invalids will draw some weird tiles. Input is typed in after first line

i=as.numeric(unlist(strsplit(readline(),"[.]")))
e=c()
for(n in 1:length(i)){
o=sum(c(0,180-360/i[1:n-1]))
for(z in 1:i[n]){
e=c(e,(360/i[n])*(z-1)+o)
}
}
f=pi/180
plot(c(0,cumsum(sin(e*f))),c(0,cumsum(cos(e*f))),type="l")


## Step #1,#2 & #3: 1898

Finally got back to it. Most of this is taken up with setting offsets and handling special cases :). Edit: V flag for duals are now handled

The general process is:

• Take the input and make a list
• Create a list of angles to draw the initial tile
• Calculate centres of each polygon it the tile and the vectors from them to bisect the edges
• Determine the tile set being drawn and make a list of angle offsets. Some tiles have additional polygons added to them to assist with filling holes.
• Draw the tiles
• Draw the duals

I can probably still golf this a bit more.

##Get input (Enter by itself then type in the tile scheme)
## Run once i is set
q=0
if(substr(i[1],1,1)=="V"){q=1;i[1]=substr(i[1],2,9)}
i=as.numeric(i)
f=pi/180
e=x=y=q=p=c()
l=length(i)
d=1/(2*tan(pi/3))
g=1/(2*sin(pi/3))
for(n in 1:l){o=sum(c(0,180-360/i[1:n-1]))
r=1/(2*sin(pi/i[n]))
a=o+(180-360/i[n])/2
b=1/(2*tan(pi/i[n]))+d
for(z in 1:i[n]){x=c(x,r*sin(a*f))
y=c(y,r*cos(a*f))
q=c(q,b)
p=c(p,(360/i[n])*(z-1)+o-90)
e=c(e,(360/i[n])*(z-1)+o)}}
if(sum(i)==18&l==6){h=c(60,0);w=c(60,120)}
if(sum(i)==18&l==5){h=c(0,0,60);w=c(60,120,60)
e=c(e,0,-60,60,180,60,180)
x=c(x,g*sin(-30*f),g*sin(-30*f),g*sin(90*f))
y=c(y,1+g*cos(-30*f),1+g*cos(-30*f),1)
q=c(q,d+d,d+d,d+d)
p=c(p,-30,90,-30)}
if(sum(i)==17&l==5&sum(abs(diff(c(i,i[1]),1)))==2){h=c(0,0);w=c(90,60)}
if(sum(i)==17&l==5&sum(abs(diff(c(i,i[1]),1)))==4){h=c(0,30);w=c(270,300)}
if(sum(i)==17&l==4){h=c(0,30,-30);w=c(60,30,90)
e=c(e,150,120,210,300)
x=c(x,sin(150*f)+g*sin(90*f),sin(150*f)+sin(210*f)/2)
y=c(y,cos(150*f)+(1/(2*cos(pi/3)))*cos(90*f),cos(150*f)+cos(210*f)/2)
q=c(q,1,1)
p=c(p,210,120)}
if(sum(i)==18&l==4){h=c(0,0);w=c(120,120)}
if(sum(i)==16&l==4){h=c(0,0);w=c(90,90)}
if(sum(i)==27&l==3){h=c(0,-30,0,30);w=c(60,90,120,150,180)}
if(sum(i)==22&l==3){h=c(0,-30,30,90,60,30)
w=c(90,150,120,90,60,30)
e=c(e,0,-30,-60,30,120,210,30,90,150)
q=q-d+1/(2*tan(pi/4));q[13]=q[17]=q[21]=q[21]+3}
if(sum(i)==20&l==3){h=c(0,-45,-90);w=c(90,0,45)}
if(sum(i)==18&l==3){h=c(0,60,0,-60);w=c(0,60,120,60)}
hx=sum(sin(h*f))
hy=sum(cos(h*f))
wx=sum(sin(w*f))
wy=sum(cos(w*f))
plot(0,0,type="n")
par(pin=c(5,5),usr=c(0,20,0,20))
for(c in -20:20){for(j in -20:20){lines(c((c*hx)+(j*wx)+0,(c*hx)+(j*wx)+cumsum(sin(e*f))),c((c*hy)+(j*wy)+0,(c*hy)+(j*wy)+cumsum(cos(e*f))),type="l")
if(q){for(n in 1:length(x)){lines(c((c*hx)+(j*wx)+x[n],(c*hx)+(j*wx)+x[n]+q[n]*sin(p[n]*f)),c((c*hy)+(j*wy)+y[n],(c*hy)+(j*wy)+y[n]+q[n]*cos(p[n]*f)),col="RED")}}}}


• Wow, only 4 hours behind me. And they look nice too, +1! Have you got all cases working yet? – Level River St Nov 18 '14 at 6:33
• @steveverrill Thanks and it works for all the cases in the question. – MickyT Nov 18 '14 at 18:24

# BBC BASIC

Level 1

Level 1.5

Level 1.5 is my own designation, but it is an important milestone in my method.

Translating the vertex figures does not always lead to the correct tiling. In some cases lines are missing.

My solution to this is to go around the largest polygon, drawing the vertex figure for every second vertex of that polygon. This is a general solution for all cases. Note that the largest polygon always has an even number of sides and the vertex figure often alternates clockwise/anticlockwise as you go around the polygon. This can be seen most clearly with 4.6.12, but it is also true of 4.8.8 and 3.12.12: when viewed from any particular 8-gon or 12-gon, alternating vertices are mirror images of each other. This is also what is happening, somewhat less obviously, with 3.3.3.4.4 and 3.3.4.3.4: when viewed from any particular square, alternating vertices are mirror images of each other.

The algorithm I use to move 2 sides around the polygon is to always do 14 iterations of the edge-drawing loop, regardless of how many edges the polygon has. 8 is a factor of 16, therefore when drawing octagons the graphics cursor ends up 16-14=2 vertices behind where it started. 3- 4- 6- and 12- gons all have sides that are factors of 12, so the graphics cursor ends up 14-12=2 vertices ahead of where it started.

The figures can be seen below. Tomorrow I hope to work out the correct translations to complete the tiling. In all cases sufficient lines are drawn to complete level 2 with translations only. In some cases a great deal more than the minimum required is drawn, but there's no problem with overlap: the rules say nothing about drawing lines only once :-)

In general, the largest polygon is the last one on the list. There is, unfortunately one case where this is not so: 3.4.6.4 Therefore the figure drawn in this case is centred on a square rather than a hexagon. There are enough lines to complete level 2 using only translations, although there will certain squares that are not drawn explicitly. This will present some problems in level 3 (fortunately I think I know how to solve this.) Similarly with 3.3.3.3.6 there are enough lines to complete level 2 using only translations, but there will be certain triangles that are not drawn explicitly.

Code

The code for level 1.5 is commented out, only the code for level 1 is activated. There are four lines beginning with a REM. Remove these REMs to activate level 1.5.

  t=PI*2                                          :REM constant Tau = PI*2
DIMm(9)                                         :REM declare array for the numbers in the input
c=0                                             :REM number of polygons in the list

INPUTz$FORi=1TOLEN(z$)                                 :REM for each character in the input
d%=VAL(MID$(z$,i))                            :REM use VAL to return the numeric value of the substring to the right and store to integer variable
IF d% c+=1 :m(c)=d%: i-=d%=12                 :REM if the last character read was a number, d% contains it, otherwise 0. Advance c and store to m. If it is 12, increment i to skip a character.
NEXT

FORi=1TOc PRINTm(i),:NEXT                       :REM parsing check for debugging.

a=601:b=601                                     :REM coordinates to start drawing at
p=40:q=0                                        :REM vector of first line

REM FORk=1TOm(c)/2                              :REM draw half as many vertex figures as there are sides on the last polygon in the list

FORj=1TOc                                       :REM for each polygon on the list
n=m(j)                                        :REM n=number of sides

w=-p*COS(t/n)-q*SIN(t/n)                      :REM rotate the starting vector anticlockwise by the internal angle of the current polygon
q=p*SIN(t/n)-q*COS(t/n)                       :REM to avoid overlapping the previous one, if any.
p=w

u=p:v=q                                       :REM make a local copy of the vector and coordinates
x=a:y=b                                       :REM to avoid corruption of p,q,a,b during the drawing of the polygon
MOVE x,y                                      :REM move the graphics cursor to the start without drawing
FORi=1TO14                                    :REM do 14 iterations regardless of the number of sides on the polygon
x+=u*2                                      :REM increment x and y by the vector representing the side
y+=v*2                                      :REM the value is double (u,v) to facilitate drawing duals later
IFVAL(z\$) DRAW x,y ELSE LINEx-u,y-v,x-u,y-v :REM if the first character of the input is a number, draw the side of the polygon. The ELSE part is unfinished and will be for drawing duals.
w=v*COS(t/n)-u*SIN(t/n)                     :REM rotate the vector clockwise
u=v*SIN(t/n)+u*COS(t/n)                     :REM through the external angle of the polygon
v=w
NEXT                                          :REM draw next edge of the current polygon
NEXT                                            :REM draw next polygon of the current vertex

REM p=u:q=v                                     :REM once the vertex is finished, we will be two sides around the perimeter of the last polygon.
REM a=x:b=y                                     :REM copy the position and direction data into p,q,a,b.
REM NEXT                                        :REM draw next vertex figure
`

Levels 2 and 3