diff --git a/edit_stack_form.php b/edit_stack_form.php
index 1bea6c665500385fc696ab98beec1a1fb469980a..9f2f313e78f5ac102adddb5bef8d813504ddc149 100644
--- a/edit_stack_form.php
+++ b/edit_stack_form.php
@@ -500,8 +500,15 @@ class qtype_stack_edit_form extends question_edit_form {
         $mform->addElement('static', $prtname . 'inputsnote', '',
                 stack_string('prtwillbecomeactivewhen', html_writer::tag('b', $inputnames)));
 
-        $mform->addElement('static', $prtname . 'graph', '',
-                stack_abstract_graph_svg_renderer::render($graph, $prtname . 'graphsvg'));
+        $tablerow = array(stack_abstract_graph_svg_renderer::render($graph, $prtname . 'graphsvg'),
+            stack_prt_graph_text_renderer::render($graph));
+        $html = '';
+        foreach ($tablerow as $td) {
+            $html .= html_writer::tag('td', $td);
+        }
+        $html = html_writer::tag('tr', $html);
+        $html = html_writer::tag('table', $html);
+        $mform->addElement('static', $prtname . 'graph', '', $html);
 
         $nextnodechoices = array('-1' => stack_string('stop'));
         foreach ($graph->get_nodes() as $node) {
diff --git a/lang/en/qtype_stack.php b/lang/en/qtype_stack.php
index ced03985bafff179bf32d7d5e12880dc4a906de4..f65ceaabbbc3e554c7997ad73f44196ed1fa83d5 100644
--- a/lang/en/qtype_stack.php
+++ b/lang/en/qtype_stack.php
@@ -310,6 +310,9 @@ $string['questionvariables_link'] = '%%WWWROOT%%/question/type/stack/doc/doc.php
 $string['questionvariablevalues'] = 'Question variable values';
 $string['quiet'] = 'Quiet';
 $string['quiet_help'] = 'When set to yes any feedback automatically generated by the answer tests is suppressed, and not displayed to the student.  The feedback fields in the branches are unaffected by this option.';
+// The icon fa-volume-off isn't very good really.
+$string['quiet_icon_true']  = '<span style="font-size: 1.25em; color:red;"><i class="fa fa-microphone-slash" aria-hidden="true"></i></span>';
+$string['quiet_icon_false'] = '<span style="font-size: 1.25em; color:blue;"><i class="fa fa-commenting-o"></i></span>';
 $string['renamequestionparts'] = 'Rename parts of the question';
 $string['requiredfield'] = 'This field is required!';
 $string['requirelowestterms'] = 'Require lowest terms';
@@ -354,7 +357,7 @@ $string['testoptions_link'] = '%%WWWROOT%%/question/type/stack/doc/doc.php/Autho
 $string['testoptionsinvalid'] = 'The test options are invalid: {$a}';
 $string['testoptionsrequired'] = 'Test options are required for this test.';
 $string['description'] = 'Description';
-$string['description_err'] = 'The node description is longer than 32 characters.';
+$string['description_err'] = 'The node description is longer than 255 characters.';
 $string['testoptions_help'] = 'This field the teacher to record the purpose of the test';
 $string['testoptions_link'] = '%%WWWROOT%%/question/type/stack/doc/doc.php/Authoring/Potential_response_trees.md';
 $string['truebranch'] = 'True branch';
diff --git a/questiontestreport.php b/questiontestreport.php
index 63e0c1ac55fdedaac80354143c28d86c1c8d3002..660052ba7210a0aed285539c589a1489688862ca 100644
--- a/questiontestreport.php
+++ b/questiontestreport.php
@@ -354,17 +354,7 @@ foreach ($question->prts as $prtname => $prt) {
 
     $graph = $prt->get_prt_graph();
     $tablerow[] = stack_abstract_graph_svg_renderer::render($graph, $prtname . 'graphsvg');
-
-    $nodes = $prt->get_nodes_summary();
-    $fields = array('displayname', 'answertest', 'trueanswernote', 'falseanswernote');
-    foreach ($fields as $field) {
-        $textsummary = array();
-        foreach ($nodes as $key => $node) {
-            $textsummary[] = $node->$field;
-        }
-        $textsummary = html_writer::tag('pre', s(implode("\n", $textsummary)));
-        $tablerow[] = html_writer::tag('div', $textsummary, array('class' => 'questionvariables'));
-    }
+    $tablerow[] = stack_prt_graph_text_renderer::render($graph);
 
     $maxima = html_writer::tag('summary', $prtname) . html_writer::tag('pre', s($prt->get_maxima_representation()));
     $maxima = html_writer::tag('details', $maxima);
@@ -412,17 +402,7 @@ foreach ($question->prts as $prtname => $prt) {
 
         $graph = $prt->get_prt_graph();
         $tablerow[] = stack_abstract_graph_svg_renderer::render($graph, $prtname . 'graphsvg');
-
-        $nodes = $prt->get_nodes_summary();
-        $fields = array('displayname', 'answertest', 'trueanswernote', 'falseanswernote');
-        foreach ($fields as $field) {
-            $textsummary = array();
-            foreach ($nodes as $key => $node) {
-                $textsummary[] = $node->$field;
-            }
-            $textsummary = html_writer::tag('pre', s(implode("\n", $textsummary)));
-            $tablerow[] = html_writer::tag('div', $textsummary, array('class' => 'questionvariables'));
-        }
+        $tablerow[] = stack_prt_graph_text_renderer::render($graph);
 
         $maxima = html_writer::tag('pre', s($sumout[$prtname]));
         $tablerow[] = html_writer::tag('div', $maxima, array('class' => 'questionvariables'));
diff --git a/questiontype.php b/questiontype.php
index bceb9298c0cfc4cf8f9c1f85c4fdecdb7c0e3856..f70960dc3d9805ac5dd6341f36ad167bb2d42fc6 100644
--- a/questiontype.php
+++ b/questiontype.php
@@ -2095,7 +2095,7 @@ class qtype_stack extends question_type {
         }
 
         $description = $fromform[$prtname . 'description'][$nodekey];
-        if (mb_strlen($description) > 32) {
+        if (mb_strlen($description) > 255) {
             $errors[$nodegroup][] = stack_string('description_err');
         }
 
@@ -2278,7 +2278,7 @@ class qtype_stack extends question_type {
                 if (is_numeric($fs)) {
                     $fs = round($fs, 2);
                 }
-                $graph->add_node($key + 1, $description, $left, $right,
+                $graph->add_prt_node($key + 1, $description[$key], $left, $right,
                         $truescoremode[$key] . $ts,
                         $falsescoremode[$key] . $fs,
                         '#fgroup_id_' . $prtname . 'node_' . $key);
@@ -2315,10 +2315,14 @@ class qtype_stack extends question_type {
                 } else {
                     $right = $node->falsenextnode + 1;
                 }
-                $graph->add_node($node->nodename + 1, $node->description, $left, $right,
+                $graph->add_prt_node($node->nodename + 1, $node->description, $left, $right,
                         $node->truescoremode . $node->truescore,
                         $node->falsescoremode . $node->falsescore,
                         '#fgroup_id_' . $prtname . 'node_' . $node->nodename);
+                // Generate a text-based representation of the cas command.
+                $at = stack_potentialresponse_tree_lite::compile_node_answertest($node);
+                $graph->add_prt_text($node->nodename + 1, $at, $node->quiet,
+                    $node->trueanswernote, $node->falseanswernote);
             }
             $graph->layout();
             $this->prtgraph[$prtname] = $graph;
@@ -2326,8 +2330,9 @@ class qtype_stack extends question_type {
         }
 
         // Otherwise, it is a new PRT. Just one node.
+        // And we don't add any text-based information for new PRTs.
         $graph = new stack_abstract_graph();
-        $graph->add_node('1', '', null, null, '=1', '=0', '#fgroup_id_' . $prtname . 'node_0');
+        $graph->add_prt_node('1', '', null, null, '=1', '=0', '#fgroup_id_' . $prtname . 'node_0');
         $graph->layout();
         $this->prtgraph[$prtname] = $graph;
         return $graph;
diff --git a/stack/graphlayout/graph.php b/stack/graphlayout/graph.php
index db926fa763e32cb10d0ecbcaba17cd17ed533ee4..7e85b6f6d2a73eb8d8e2ff44ea5d1f7773bc770b 100644
--- a/stack/graphlayout/graph.php
+++ b/stack/graphlayout/graph.php
@@ -25,9 +25,10 @@
 
 defined('MOODLE_INTERNAL') || die();
 
-require_once(__DIR__ . '/graphnode.php');
+require_once(__DIR__ . '/prtnode.php');
 require_once(__DIR__ . '/graphclump.php');
 require_once(__DIR__ . '/svgrenderer.php');
+require_once(__DIR__ . '/textrenderer.php');
 
 /**
  * Abstract representation of a graph (e.g. a PRT).
@@ -82,6 +83,30 @@ class stack_abstract_graph {
                 $leftlabel, $rightlabel, $url);
     }
 
+    /**
+     * Add a prt node to the graph.  These nodes have more text-based fields for better representation.
+     *
+     * @param string $name name of the node to add.
+     * @param string $description text-based description of the node to add.
+     * @param string $leftchild name of the left child node.
+     * @param string $rightchild name of the right child node.
+     * @param string $leftlabel lable to display on the edge to the left child.
+     * @param string $rightlabel lable to display on the edge to the right child.
+     * @param string $url if set, this node should be a link to that URL.
+     */
+    public function add_prt_node($name, $description, $leftchild, $rightchild, $leftlabel = '', $rightlabel = '', $url = '') {
+        $this->nodes[$name] = new stack_prt_graph_node($name, $description, $leftchild, $rightchild,
+            $leftlabel, $rightlabel, $url);
+    }
+
+    public function add_prt_text($name, $casstatement, $quiet, $truenote, $falsenote) {
+        if ($this->nodes[$name] instanceof stack_prt_graph_node) {
+            $this->nodes[$name]->add_prt_text($casstatement, $quiet, $truenote, $falsenote);
+        } else {
+            throw new stack_exception('Trying to add text-based fields to the wrong kind of node.');
+        }
+    }
+
     public function remove_node($nametodelete) {
         foreach ($this->nodes as $name => $node) {
             if ($name == $nametodelete) {
diff --git a/stack/graphlayout/prtnode.php b/stack/graphlayout/prtnode.php
new file mode 100644
index 0000000000000000000000000000000000000000..874a6f5acce5a2c6793ce97d1fe4228994f70397
--- /dev/null
+++ b/stack/graphlayout/prtnode.php
@@ -0,0 +1,62 @@
+<?php
+// This file is part of Stack - http://stack.maths.ed.ac.uk/
+//
+// Stack is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Stack is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Stack.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * Class to represent a vertex in an abstract graph of a PRT.
+ *
+ * @package   qtype_stack
+ * @copyright 2013 The Open University
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/graphnode.php');
+
+/**
+ * Represents a node in a STACK PRT extending {@link stack_abstract_graph}.
+ *
+ * @copyright 2023 The University of Edinburgh
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class stack_prt_graph_node extends stack_abstract_graph_node {
+    /**
+     * @var string statement sent to Maxima by this node.
+     */
+    public $casstatement;
+
+    /**
+     * @var boolean Is the feedback from this test igored?
+     */
+    public $quiet;
+
+    /**
+     * @var string Note create by the true branch.
+     */
+    public $truenote;
+
+    /**
+     * @var string Note create by the false branch.
+     */
+    public $falsenote;
+
+    public function add_prt_text($casstatement, $quiet, $truenote, $falsenote) {
+        $this->casstatement = $casstatement;
+        $this->quiet        = $quiet;
+        $this->truenote     = $truenote;
+        $this->falsenote    = $falsenote;
+    }
+}
diff --git a/stack/graphlayout/textrenderer.php b/stack/graphlayout/textrenderer.php
new file mode 100644
index 0000000000000000000000000000000000000000..324350adf1c1cd44eb3025f9987a3a5c584fcb18
--- /dev/null
+++ b/stack/graphlayout/textrenderer.php
@@ -0,0 +1,83 @@
+<?php
+// This file is part of Stack - http://stack.maths.ed.ac.uk/
+//
+// Stack is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Stack is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Stack.  If not, see <http://www.gnu.org/licenses/>.
+
+
+/**
+ * Displays a prt graph using an html table with text.
+ *
+ * @package   qtype_stack
+ * @copyright 2023 The University of Edinburgh
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+/**
+ * Displays a {@link stack_abstract_graph} as text.
+ *
+ * @copyright 2023 The University of Edinburgh
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class stack_prt_graph_text_renderer {
+    /**
+     * Output a graph as SVG.
+     * @param stack_abstract_graph $g the graph to display.
+     * @param string $id an id to add to the SVG node in the HTML.
+     */
+    public static function render(stack_abstract_graph $g) {
+        $renderer = new self($g);
+        return $renderer->to_html();
+    }
+
+    /**
+     * Constructor.
+     * @param stack_abstract_graph $g the graph to display.
+     */
+    protected function __construct(stack_abstract_graph $g) {
+        $this->g = $g;
+    }
+
+    /**
+     * Actually generate the HTML for the nodes in the graph.
+     * @return string HTML code. Can be embedded straight into a HTML page.
+     */
+    protected function to_html() {
+
+        $table = array();
+        foreach ($this->g->get_nodes() as $node) {
+            $quiet = stack_string('quiet_icon_false');
+            if ($node->quiet) {
+                $quiet = stack_string('quiet_icon_true');
+            }
+            // Put the name and description in one cell. It looks better.
+            $table[] = array($node->name . '. ' . $node->description,
+                    html_writer::tag('code', s($node->casstatement)), $quiet,
+                            $node->truenote, $node->falsenote);
+        }
+
+        $html = '';
+        foreach ($table as $tablerow) {
+            $row = '';
+            foreach ($tablerow as $td) {
+                $row .= html_writer::tag('td', $td);
+            }
+            $html .= html_writer::tag('tr', $row) . "\n";
+        }
+        // TODO: style the table with more padding.
+        $html = html_writer::start_tag('table', array('class' => 'prttexttable')) . $html .
+                html_writer::end_tag('table');
+
+        return $html;
+    }
+}
diff --git a/stack/prt.class.php b/stack/prt.class.php
index 66fe0d111fb2da5720d20e25875cda4cca6cbd3a..3490d88672b4867a4f4a86a7fec1a3962d045490 100644
--- a/stack/prt.class.php
+++ b/stack/prt.class.php
@@ -286,6 +286,7 @@ class stack_potentialresponse_tree_lite {
             $n->falseanswernote = $node->falseanswernote;
             $n->falsescore      = $node->falsescore;
             $n->falsescoremode  = $node->falsescoremode;
+            $n->quiet           = $node->quiet;
             $n->answertest      = $this->compile_node_answertest($node);
             $name = (((int) $node->nodename) + 1);
             if (trim($node->description) !== '') {
@@ -557,7 +558,7 @@ class stack_potentialresponse_tree_lite {
     /*
      * Generate the complete maxima command for a single answertest in a specific node.
      */
-    private function compile_node_answertest($node) {
+    public static function compile_node_answertest($node) {
         // TODO: make this saner, the way Stateful lets the tests do their own
         // call construction might duplicate things but it does not require this
         // much knowledge about the shape of things.
@@ -868,8 +869,10 @@ class stack_potentialresponse_tree_lite {
             if ($labels && array_key_exists($node->falseanswernote, $labels)) {
                 $rlabel = $labels[$node->falseanswernote];
             }
-            $graph->add_node($key + 1, $node, $left, $right, $llabel, $rlabel,
+            $graph->add_prt_node($key + 1, $node->description, $left, $right, $llabel, $rlabel,
                 '#fgroup_id_' . $this->name . 'node_' . $key);
+            $graph->add_prt_text($node->nodename + 1, $node->answertest, $node->quiet,
+                $node->trueanswernote, $node->falseanswernote);
         }
 
         $graph->layout();