Skip to content
This repository has been archived by the owner on Dec 13, 2022. It is now read-only.

Commit

Permalink
Redesign - Animations, new head and much more (#5)
Browse files Browse the repository at this point in the history
* Added placeholder images

* Added popout window on syntax error (untested)

* Added needle drawing (programmatically)

* Added new tape loop - preliminar version

* Fully working - Preliminary

* Ready for revision 1
  • Loading branch information
margual56 committed Nov 10, 2021
1 parent 2067d57 commit 5817230
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 91 deletions.
5 changes: 5 additions & 0 deletions src/Exceptions/SyntaxError.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package Exceptions;

import javax.swing.JOptionPane;

@SuppressWarnings("serial")
public class SyntaxError extends Exception {
String str = "";

public SyntaxError() {
JOptionPane.showMessageDialog(null, "Unknown syntax error", "Syntax error", JOptionPane.ERROR_MESSAGE);
}

public SyntaxError(String text) {
str = text;

JOptionPane.showMessageDialog(null, text, "Syntax error", JOptionPane.ERROR_MESSAGE);
}

@Override
Expand Down
31 changes: 27 additions & 4 deletions src/Machines/TM.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* Basic implementation of the Turing Machine. This is not graphical, it just
* processes the tape, the states and the code.
*
* @author Marcos Gutiérrez Alonso
* @author Marcos Guti�rrez Alonso
* @version 2.0
*
*/
Expand Down Expand Up @@ -210,8 +210,7 @@ private boolean isFinal(String s) {
/**
*
*
* @param "R"
* or "L"
* @param m "R" or "L"
* @throws RuntimeError
*/
protected void move(String m) throws RuntimeError {
Expand Down Expand Up @@ -262,6 +261,18 @@ private String[] getInstruction(String s, String v) throws RuntimeError {
return toReturn;
}

public String getCurrentInstruction() throws RuntimeError {
String[] text = getInstruction(state, "" + getTape(head));
String out = "";

out += "(";
for (int i = 0; i < text.length - 1; i++)
out += text[i] + ", ";
out += text[text.length - 1] + ")\n";

return out;
}

public String getTape() {
String t = "{";

Expand All @@ -276,14 +287,22 @@ public String getTape() {
return t + "};";
}

protected String getTape(int index) {
public String getTape(int index) {
// If out of bounds, return zero (the tape is technically infinite)
if (index < 0 || index >= tape.length)
return "0";

return Character.toString(tape[index]);
}

public int getTapeLength() {
return tape.length;
}

public int getHead() {
return head;
}

@Override
public String toString() {
String out = "";
Expand Down Expand Up @@ -315,6 +334,10 @@ public String toString() {
return out;
}

public String getState() {
return state;
}

public String output() {
//if (undefined)
//return ((char) 193) + "";
Expand Down
154 changes: 113 additions & 41 deletions src/Machines/TMd.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,28 @@
* the Turing Machine and draws it to the screen. This implementation needs the
* <a href="https://processing.org/">Processing</a> "core.jar" library.
*
* @author Marcos Gutiérrez Alonso
* @author Marcos Guti�rrez Alonso
* @version 1.0
*/
public class TMd extends TM {
private float tapeCounter = 0;
private float tmpHead;
private boolean changing = false;

public TMd(Path code) throws SyntaxError, IOException {
private float transition;
private int prevHead = -1;
private String prevInstruction;

private static int MAX_CELLS = 25;

public TMd(Path code) throws SyntaxError, IOException, RuntimeError {
super(code);

tmpHead = head;

prevHead = head;
prevInstruction = getCurrentInstruction();
}

public TMd(Path code, String initialState) throws SyntaxError, IOException {
public TMd(Path code, String initialState) throws SyntaxError, IOException, RuntimeError {
super(code, initialState);

tmpHead = head;

prevHead = head;
prevInstruction = getCurrentInstruction();
}

@Override
Expand All @@ -49,8 +53,6 @@ protected void move(String m) {

this.tape = newtape;
}

changing = true;
} else if (m.equals("L")) {
this.head--;

Expand All @@ -67,8 +69,6 @@ protected void move(String m) {

this.head += 2;
}

changing = true;
}
}

Expand All @@ -87,7 +87,7 @@ public void showTapeSummary(float x, float y, float wid, float hei, PApplet app)
app.line(x, y, x + margin / 2, y + margin);
app.line(x + wid, y, x + wid - margin / 2 + 1, y + margin);

int columns = 11;
int columns = 35;
int rows = tape.length / columns;

float cs = Math.min((wid - margin * 2) / columns, (hei - margin) / rows);
Expand Down Expand Up @@ -119,34 +119,106 @@ public void showTapeSummary(float x, float y, float wid, float hei, PApplet app)
}
}

public void show(float x0, float y, float wid, float hei, int headspace, PApplet app) throws RuntimeError {
float cs = Math.min(wid / (headspace * 2), hei);

app.textAlign(PApplet.CENTER, PApplet.CENTER);
app.textSize(cs * 0.9f);

float x, offset = PApplet.lerp(tmpHead, this.head, tapeCounter);
float middle_x = x0 + wid / 2;

app.stroke(255);
for (int i = Math.min(0, this.head - headspace); i < Math.max(this.head + headspace, this.tape.length + 1); i++) {
x = middle_x + cs * (i - offset);

if (x < x0 || x >= x0 + wid)
continue;

app.fill(0);
app.rect(x, y, cs, cs);
public void show(float x0, float y0, float wid, float hei, int headspace, PApplet app){
float cs = Math.max(wid/MAX_CELLS, hei);

int len = getTapeLength();
int head = getHead();

int leftIndex, rightIndex;
if(head != prevHead) {
leftIndex = (prevHead < MAX_CELLS/2.0)? 0 : (int)Math.floor(head-MAX_CELLS/2.0);
rightIndex = (len-prevHead < MAX_CELLS/2.0)? len : (int)Math.ceil(head+MAX_CELLS/2.0);

app.pushMatrix();
app.translate(PApplet.lerp(Math.signum(head-prevHead)*cs, 0, transition), 0);
}else {
leftIndex = (prevHead < MAX_CELLS/2.0)? 0 : (int)Math.floor(prevHead-MAX_CELLS/2.0);
rightIndex = (len-prevHead < MAX_CELLS/2.0)? len : (int)Math.ceil(prevHead+MAX_CELLS/2.0);
}

float middlePoint = (x0+wid/2) - cs/2;

app.textAlign(PApplet.CENTER, PApplet.BOTTOM);
for(int i = head, index = 0; i>=leftIndex; i--, index++) {
String val = getTape(i);

if(val.equals("1")) {
app.fill(255, 0, 0, 50);
}else {
app.noFill();
}

app.rect(middlePoint-index*cs, y0, cs, cs);

app.fill(255);
app.text(val, middlePoint-index*cs + cs/2.0f, y0+cs/2);
}

for(int i = head+1, index = 1; i<rightIndex; i++, index++) {
String val = getTape(i);

if(val.equals("1")) {
app.fill(255, 0, 0, 50);
}else {
app.noFill();
}

app.rect(middlePoint+index*cs, y0, cs, cs);

app.fill(255);
app.text(getTape(i), x + cs / 2, y + cs * 0.4f);
app.text(val, middlePoint+index*cs + cs/2.0f, y0+cs/2);
}

if (tapeCounter == 1) {
tapeCounter = 0;
tmpHead = this.head;
changing = false;
} else if (changing) {
tapeCounter += 0.1;
if(head != prevHead) {
app.popMatrix();
}

app.stroke(255);
app.strokeWeight(5);
app.noFill();
needle(x0+wid/2.0f, y0+hei*1.75f, cs, getState(), app);
app.strokeWeight(1);
}

public void animateTape(float fps, PApplet app) throws RuntimeError {
if(head != prevHead) {
if(transition == 0) transition = 0.01f;
else transition += 50/(app.frameRate*fps);

if(transition > 0.99) {
transition = 0;
prevHead = head;
prevInstruction = getCurrentInstruction();
}
}
}

public boolean finishedTransition() {
return head == prevHead || transition > 0.99 ;
}

public String getInstruction() throws RuntimeError {
if(!finishedTransition() || transition <= 0.5)
return prevInstruction;
else
return getCurrentInstruction();
}

void needle(float x, float y, float size, String state, PApplet app){
float xOffset = x-size/2;
float yOffset = y-size/2;

app.beginShape();
app.vertex(size/2 + xOffset, -size/2 + yOffset);
app.vertex(size + xOffset, size/3 + yOffset);
app.vertex(size + xOffset, size + yOffset);
app.vertex(0 + xOffset, size + yOffset);
app.vertex(0 + xOffset, size/3 + yOffset);
app.endShape(PApplet.CLOSE);

app.fill(255);
app.textAlign(PApplet.CENTER, PApplet.CENTER);
app.text(state, size/2 + xOffset, size/2 + yOffset);
}
}
Loading

0 comments on commit 5817230

Please sign in to comment.