<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><br><div><div>On Aug 11, 2013, at 6:38 PM, grant centauri wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><span class="Apple-style-span" style="border-collapse: separate; font-family: 'Lucida Grande'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: -webkit-auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; font-size: medium; ">I've rewritten a number of times, and was just hoping for some design advice before I start banging my head against the wall</span></blockquote></div><br><div><br></div><div>Use the design recipe completely until it becomes second nature:&nbsp;</div><div><br></div><div>1. Separate global constants from values that change over the course of the game. [World Design]</div><div><br></div><div>2. You have vague data definitions. You lack data examples. [Function Design]</div><div><br></div><div>3. You lack contracts, but I accept that they are mostly obvious.&nbsp;</div><div><br></div><div>4. Your functions don't seem to match the data definition that they consume.&nbsp;</div><div><br></div><div>5. You lack function examples. Formulate them as tests.&nbsp;</div><div>Even after you figure out everything else, don't drop this step. Ever.&nbsp;</div><div><br></div><div>;; --------------------------------------------</div><div><br></div><div>Structures within structures are okay. As you grow up, you need to learn to use</div><div>match-define because it gives you access to several nested fields at once.&nbsp;</div><div><br></div><div>I have made your program Rackety and added some suggestions on what to look out for.&nbsp;</div><div>I never figured out what the program does or is supposed to do but I am sure my rewrite</div><div>works exactly as yours before, including all the mistakes. So they remain yours to find.&nbsp;</div><div><br></div><div>Good luck -- Matthias</div><div><br></div><div><br></div><div><br></div><div><div>#lang racket</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; interface&nbsp;</div><div><br></div><div>(provide</div><div>&nbsp;(contract-out</div><div>&nbsp; ;; start launches the game with ... as initial state and ...&nbsp;</div><div>&nbsp; (start (-&gt; text-box?))))</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; implementation&nbsp;</div><div>(require 2htdp/universe 2htdp/image)</div><div><br></div><div>(module+ test</div><div>&nbsp; (require rackunit))</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; This program ...&nbsp;</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; data definitions&nbsp;</div><div><br></div><div>;; current word is a list of chars, string-to-print is a list of strings</div><div>(struct buffer (current-word string-to-print))</div><div><br></div><div>;; defining a font structure, this is to use with the text/font function</div><div>(struct font (size color face family style weight underline?))</div><div><br></div><div>;; input is a buffer, paper is an image, font is a font, cursor-x and -y are positive integers</div><div>;; **: I consider it bad style to use an image as the state of the world or even a part of the state.</div><div>;; **: I recommend that you store the values that change and construct the image inside of render.&nbsp;</div><div>(struct text-box (input paper font cursor-x cursor-y))</div><div><br></div><div>;; World = (text-box ...)</div><div>;; Font = ...</div><div>;; Buffer = ...&nbsp;</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; sample data and constants&nbsp;</div><div><br></div><div>(define terminus-16 (font 16 'white "Terminus" 'system 'normal 'bold #f))</div><div><br></div><div>(define my-text</div><div>&nbsp; (string-append&nbsp;</div><div>&nbsp; &nbsp;"Now THIS is the string I'd like to print! &nbsp;Oh my!, it appears to be working."</div><div>&nbsp; &nbsp;"However, there are some errors in my code (such as calling first on an empty "</div><div>&nbsp; &nbsp;"list now and then) and it seems to slow down quite a bit."))</div><div><br></div><div>(define my-textbox</div><div>&nbsp; (text-box (buffer empty (string-split my-text)) (rectangle 400 300 'solid 'blue) terminus-16 10 10))</div><div><br></div><div>;; ===================================================================================================</div><div>;; the main function&nbsp;</div><div><br></div><div>(define (start)</div><div>&nbsp; (big-bang my-textbox</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (on-tick next-char)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (to-draw render)))</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; World -&gt; World&nbsp;</div><div>;; updates the "paper" so that the next character is placed on it, and updates the current-word</div><div>(define (next-char tb)</div><div>&nbsp; (match-define (text-box (buffer word s) paper font x y) tb)</div><div>&nbsp; (define char-width (image-width (game-print " " font)))</div><div>&nbsp; (cond</div><div>&nbsp; &nbsp; [(empty? word) (next-char (next-word tb))]</div><div>&nbsp; &nbsp; [else (define new-image (place-image (game-print (string (first word)) font) x y paper))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (text-box (buffer (rest word) s) new-image font (+ char-width x) y)]))</div><div><br></div><div>;; World -&gt; World&nbsp;</div><div>;; places the next word from the text-box-input's string-to-print into current-word</div><div>(define (next-word tb)</div><div>&nbsp; ;; ** the following match assumes that you have a non-empty list in the 2nd buffer position&nbsp;</div><div>&nbsp; ;; ** does your function call assure this?&nbsp;</div><div>&nbsp; (match-define (text-box (buffer _ (cons word rst)) paper font x y) tb)</div><div>&nbsp; (define word-width (image-width (game-print word font)))</div><div>&nbsp; (define paper-width (image-width paper))</div><div>&nbsp; ;; --- are the following three lines really going to vary over the course of the game, constant?&nbsp;</div><div>&nbsp; (define a-char (game-print " " font))</div><div>&nbsp; (define char-width (image-width a-char))</div><div>&nbsp; (define char-hight (image-height a-char))</div><div>&nbsp; (define line-height (+ 5 char-hight))</div><div>&nbsp; (cond ;; [(empty? s) tb] ;; **: This clause looks highly suspicious&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ;; this clause determines if we need to start a new line.</div><div>&nbsp; &nbsp; &nbsp; &nbsp; [(&gt; (+ x word-width) paper-width)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(text-box (buffer (string-&gt;list word) rst) paper font 10 (+ line-height y))]</div><div>&nbsp; &nbsp; &nbsp; &nbsp; [else&nbsp;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(text-box (buffer (string-&gt;list word) rst) paper font (+ char-width x) y)]))</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; World -&gt; Image&nbsp;</div><div>;; render the game as an image&nbsp;</div><div><br></div><div>(module+ test</div><div>&nbsp; (check-equal? (render my-textbox)</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (overlay (text-box-paper my-textbox) (empty-scene 500 450 'black))</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "testing render on the initial world"))</div><div><br></div><div>(define (render tb)</div><div>&nbsp; (overlay (text-box-paper tb) (empty-scene 500 450 'black)))</div><div><br></div><div>;; String Font -&gt; Image</div><div>;; draws string s with the font f</div><div>(define (game-print s f)&nbsp;</div><div>&nbsp; (match-define (font size color face family style weight underline?) f)</div><div>&nbsp; (text/font s size color face family style weight underline?))</div><div><br></div><div>;; ---------------------------------------------------------------------------------------------------</div><div>;; run program run&nbsp;</div><div>;; ** I recommend launching this from the repl instead.&nbsp;</div><div>;; (start)</div></div><div><br></div><div><br></div></body></html>