Skip to content

Commit 8d16897

Browse files
committed
implement TURT
1 parent a6fd146 commit 8d16897

File tree

4 files changed

+205
-0
lines changed

4 files changed

+205
-0
lines changed

README.MD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Additionally, the following fingerprints are currently supported (more to come):
6262
- [REFC](./docs/catseye/library/REFC.markdown)
6363
- [ROMA](./docs/catseye/library/ROMA.markdown)
6464
- [TOYS](./docs/catseye/library/TOYS.markdown)
65+
- [TURT](./docs/catseye/library/TURT.markdown)
6566

6667
### Version Release Checklist
6768
- Update the version number inside the [pom](./pom.xml)

src/main/java/com/falsepattern/jfunge/interpreter/instructions/Funge98.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.falsepattern.jfunge.interpreter.instructions.fingerprints.REFC;
1313
import com.falsepattern.jfunge.interpreter.instructions.fingerprints.ROMA;
1414
import com.falsepattern.jfunge.interpreter.instructions.fingerprints.TOYS;
15+
import com.falsepattern.jfunge.interpreter.instructions.fingerprints.TURT;
1516
import com.falsepattern.jfunge.interpreter.instructions.fingerprints._3DSP;
1617
import com.falsepattern.jfunge.ip.IStack;
1718
import com.falsepattern.jfunge.ip.impl.Stack;
@@ -51,6 +52,7 @@ public class Funge98 implements InstructionSet {
5152
addFingerprint(REFC.INSTANCE);
5253
addFingerprint(ROMA.INSTANCE);
5354
addFingerprint(TOYS.INSTANCE);
55+
addFingerprint(TURT.INSTANCE);
5456
}
5557

5658
private static void addFingerprint(Fingerprint print) {
Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
package com.falsepattern.jfunge.interpreter.instructions.fingerprints;
2+
3+
import com.falsepattern.jfunge.interpreter.ExecutionContext;
4+
import com.falsepattern.jfunge.interpreter.instructions.Fingerprint;
5+
import com.falsepattern.jfunge.util.MemoryStack;
6+
import lombok.AccessLevel;
7+
import lombok.Cleanup;
8+
import lombok.NoArgsConstructor;
9+
import lombok.val;
10+
import org.joml.Math;
11+
import org.joml.Matrix3x2f;
12+
import org.joml.Vector2f;
13+
import org.joml.Vector2i;
14+
15+
import javax.imageio.ImageIO;
16+
import java.awt.Color;
17+
import java.awt.Graphics2D;
18+
import java.awt.image.BufferedImage;
19+
import java.io.File;
20+
import java.io.IOException;
21+
import java.nio.file.Paths;
22+
23+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
24+
public class TURT implements Fingerprint {
25+
public static final TURT INSTANCE = new TURT();
26+
27+
private static BufferedImage image;
28+
private static Graphics2D gfx;
29+
30+
private static Vector2i dimensions;
31+
private static Vector2f position;
32+
private static Color lineColor;
33+
private static boolean penDown;
34+
private static int angle;
35+
36+
static {
37+
initialize(new Vector2i(500, 500), new Vector2i(0, 0));
38+
}
39+
40+
public static void initialize(Vector2i dimensions, Vector2i initialPosition) {
41+
TURT.dimensions = new Vector2i(dimensions);
42+
TURT.position = new Vector2f(initialPosition);
43+
TURT.angle = 0;
44+
TURT.penDown = false;
45+
46+
TURT.image = new BufferedImage(dimensions.x, dimensions.y, BufferedImage.TYPE_INT_RGB);
47+
TURT.gfx = image.createGraphics();
48+
gfx.setColor(Color.WHITE);
49+
gfx.fillRect(0, 0, dimensions.x, dimensions.y);
50+
gfx.setColor(lineColor = Color.BLACK);
51+
}
52+
53+
private static void clampPos() {
54+
if (position.x < 0) {
55+
position.x = 0;
56+
}
57+
if (position.x > dimensions.x - 1) {
58+
position.x = dimensions.x - 1;
59+
}
60+
if (position.y < 0) {
61+
position.y = 0;
62+
}
63+
if (position.y > dimensions.y - 1) {
64+
position.y = dimensions.y - 1;
65+
}
66+
}
67+
68+
@Instr('L')
69+
public static void turnLeft(ExecutionContext ctx) {
70+
angle = (((angle + ctx.stack().pop()) % 360) + 360) % 360;
71+
}
72+
73+
@Instr('R')
74+
public static void turnRight(ExecutionContext ctx) {
75+
angle = (((angle - ctx.stack().pop()) % 360) + 360) % 360;
76+
}
77+
78+
@Instr('H')
79+
public static void setHeading(ExecutionContext ctx) {
80+
angle = ((ctx.stack().pop() % 360) + 360) % 360;
81+
}
82+
83+
@Instr('F')
84+
public static void forward(ExecutionContext ctx) {
85+
@Cleanup val mem = MemoryStack.stackPush();
86+
val newPos = mem.vec2f().set(1, 0);
87+
new Matrix3x2f().rotation(Math.toRadians(-angle)).transformDirection(newPos);
88+
val step = ctx.stack().pop();
89+
if (penDown) {
90+
newPos.mul(step).add(position);
91+
gfx.drawLine((int) position.x, (int) position.y, (int) newPos.x, (int) newPos.y);
92+
position.set(newPos);
93+
} else {
94+
position.add(newPos.mul(step));
95+
}
96+
clampPos();
97+
}
98+
99+
@Instr('B')
100+
public static void back(ExecutionContext ctx) {
101+
@Cleanup val mem = MemoryStack.stackPush();
102+
val newPos = mem.vec2f().set(1, 0);
103+
new Matrix3x2f().rotation(Math.toRadians(-angle)).transformDirection(newPos);
104+
val step = ctx.stack().pop();
105+
if (penDown) {
106+
newPos.mul(-step).add(position);
107+
gfx.drawLine((int) position.x, (int) position.y, (int) newPos.x, (int) newPos.y);
108+
position.set(newPos);
109+
} else {
110+
position.add(newPos.mul(-step));
111+
}
112+
clampPos();
113+
}
114+
115+
@Instr('P')
116+
public static void penPos(ExecutionContext ctx) {
117+
penDown = ctx.stack().pop() != 0;
118+
}
119+
120+
@Instr('C')
121+
public static void penColor(ExecutionContext ctx) {
122+
val rgb = ctx.stack().pop() & 0xFFFFFF;
123+
lineColor = new Color(rgb);
124+
gfx.setColor(lineColor);
125+
}
126+
127+
@Instr('N')
128+
public static void clearPaper(ExecutionContext ctx) {
129+
val rgb = ctx.stack().pop() & 0xFFFFFF;
130+
gfx.setColor(new Color(rgb));
131+
gfx.fillRect(0, 0, dimensions.x, dimensions.y);
132+
gfx.setColor(lineColor);
133+
}
134+
135+
@Instr('D')
136+
public static void showDisplay(ExecutionContext ctx) {
137+
System.err.println("TODO: TURT 'D' unsupported. Popping stack, but not displaying.");
138+
ctx.stack().pop();
139+
}
140+
141+
@Instr('T')
142+
public static void teleport(ExecutionContext ctx) {
143+
val stack = ctx.stack();
144+
position.y = stack.pop();
145+
position.x = stack.pop();
146+
}
147+
148+
@Instr('E')
149+
public static void queryPen(ExecutionContext ctx) {
150+
ctx.stack().push(penDown ? 1 : 0);
151+
}
152+
153+
@Instr('A')
154+
public static void queryHeading(ExecutionContext ctx) {
155+
ctx.stack().push(angle);
156+
}
157+
158+
@Instr('Q')
159+
public static void queryPosition(ExecutionContext ctx) {
160+
val stack = ctx.stack();
161+
stack.push((int) position.x);
162+
stack.push((int) position.y);
163+
}
164+
165+
@Instr('U')
166+
public static void queryBounds(ExecutionContext ctx) {
167+
val stack = ctx.stack();
168+
stack.push(0);
169+
stack.push(0);
170+
stack.push(dimensions.x);
171+
stack.push(dimensions.y);
172+
}
173+
174+
@Instr('I')
175+
public static void printDrawing(ExecutionContext ctx) {
176+
File file;
177+
int counter = 0;
178+
do {
179+
file = Paths.get(".", "turtle" + (counter++) + ".png").toFile();
180+
} while (file.exists());
181+
try {
182+
ImageIO.write(image, "PNG", file);
183+
} catch (IOException e) {
184+
e.printStackTrace();
185+
ctx.interpret('r');
186+
}
187+
}
188+
189+
@Override
190+
public int code() {
191+
return 0x54555254;
192+
}
193+
}

src/main/java/com/falsepattern/jfunge/util/MemoryStack.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.falsepattern.jfunge.util;
22

33
import org.joml.Matrix4f;
4+
import org.joml.Vector2f;
45
import org.joml.Vector2i;
56
import org.joml.Vector3f;
67
import org.joml.Vector3i;
@@ -18,6 +19,8 @@ public class MemoryStack implements AutoCloseable{
1819
Vector3f::zero);
1920
private final RewindableCachingStorage<Vector2i> vec2i = new RewindableCachingStorage<>(Vector2i::new,
2021
Vector2i::zero);
22+
private final RewindableCachingStorage<Vector2f> vec2f = new RewindableCachingStorage<>(Vector2f::new,
23+
Vector2f::zero);
2124

2225
public static MemoryStack stackPush() {
2326
return THREAD_LOCAL.get().push();
@@ -39,11 +42,16 @@ public Vector2i vec2i() {
3942
return vec2i.alloc();
4043
}
4144

45+
public Vector2f vec2f() {
46+
return vec2f.alloc();
47+
}
48+
4249
public MemoryStack push() {
4350
mat4f.mark();
4451
vec3i.mark();
4552
vec3f.mark();
4653
vec2i.mark();
54+
vec2f.mark();
4755
depth++;
4856
return this;
4957
}
@@ -57,6 +65,7 @@ public void pop() {
5765
vec3i.unmark();
5866
vec3f.unmark();
5967
vec2i.unmark();
68+
vec2f.unmark();
6069
}
6170

6271
@Override

0 commit comments

Comments
 (0)