I'm happy to share this program that I made in c, using the CE C/C++ Toolchain. It's called the Sentence Generator

The program generates random, plausible, sentences(yes I'm aware that they don't really make sense) from defined structures and word lists. You'll get everything from boring statements to funny combinations.

Features:
    Random Generation: Always unique by using the real-time clock.
    Variety of Words: It includes many different types of words.
    Structured templates: It uses predefined structures to guide the sentences.
    Basic Agreement: Tries to make it keep agreement between subjects.
    Graphical Display: Uses the graphx module to display the sentences.
    Word Wrapping: Longer sentences wrap onto the next line.
    Simple Controls: Very easy to use.


Here is a screenshot:

Here is the code in c:

Code:
#include <graphx.h>
#include <keypadc.h>
#include <stdlib.h>
#include <string.h>
#include <tice.h> // Used for rtc_Time() for srand seed
#include <stdint.h>
#include <ctype.h> // Used for toupper()

#define MAX_WORDS 15
#define MAX_SENTENCE_LENGTH 256

// --- Colors ---
#define COLOR_BLACK 0
#define COLOR_WHITE 255

// --- Data ---
const char *articles_singular[] = {"the", "a", "my", "your", "his", "her", "our", "their", "this", "that", "each", "every", "another", "one"};
const char *articles_plural[] = {"the", "my", "your", "his", "her", "our", "their", "these", "those", "all", "some", "many", "few"};
const char *adjectives[] = {"happy", "silly", "fast", "blue", "big", "small", "red", "brave", "quiet", "loud", "clever", "gentle", "wild", "calm", "strange", "old", "young", "new", "good", "bad", "beautiful", "ugly", "bright", "dark", "strong", "weak", "soft", "hard", "long", "short", "tall", "short", "heavy", "light", "funny", "serious", "delicious", "awful", "lovely", "horrible", "quick", "slow", "smart", "foolish", "rich", "poor", "famous", "shy", "energetic", "lazy", "kind", "cruel", "polite", "rude", "honest", "dishonest", "loyal", "disloyal", "patient", "impatient", "generous", "selfish", "optimistic", "pessimistic", "cheerful", "gloomy", "peaceful", "noisy", "careful", "careless", "creative", "boring", "popular", "unpopular", "healthy", "sick", "wise", "naive", "grateful", "ungrateful"};
const char *nouns_singular[] = {"cat", "dog", "bird", "car", "tree", "house", "book", "computer", "flower", "sun", "moon", "star", "river", "mountain", "cloud", "ocean", "friend", "teacher", "student", "ball", "game", "song", "apple", "banana", "orange", "grape", "table", "chair", "desk", "phone", "clock", "shoe", "hat", "coat", "shirt", "pants", "skirt", "dress", "cup", "plate", "knife", "fork", "spoon", "glass", "bottle", "door", "window", "wall", "floor", "ceiling", "bed", "pillow", "blanket", "lamp", "key", "lock", "pen", "pencil", "paper", "picture", "radio", "television", "camera", "watch", "money", "ticket", "ticket", "plane", "train", "bus", "boat", "bike", "map", "globe", "city", "country", "world", "planet", "galaxy", "universe", "beach", "forest", "park", "school", "hospital", "restaurant", "store", "museum", "library", "office", "factory", "bridge", "road", "path", "sky", "earth", "wind", "rain", "snow", "ice", "fire", "water", "stone", "wood", "metal", "music", "movie", "art", "dance", "sport", "team", "idea", "dream", "plan", "reason", "problem", "solution", "question", "answer", "story", "poem", "letter", "message", "secret", "promise", "gift", "toy", "tool", "machine", "plant", "animal", "person", "child", "man", "woman", "king", "queen", "prince", "princess", "hero", "villain"};
const char *nouns_plural[] = {"cats", "dogs", "birds", "cars", "trees", "houses", "books", "computers", "flowers", "suns", "moons", "stars", "rivers", "mountains", "clouds", "oceans", "friends", "teachers", "students", "balls", "games", "songs", "apples", "bananas", "oranges", "grapes", "tables", "chairs", "desks", "phones", "clocks", "shoes", "hats", "coats", "shirts", "pants", "skirts", "dresses", "cups", "plates", "knives", "forks", "spoons", "glasses", "bottles", "doors", "windows", "walls", "floors", "ceilings", "beds", "pillows", "blankets", "lamps", "keys", "locks", "pens", "pencils", "papers", "pictures", "radios", "televisions", "cameras", "watches", "money", "tickets", "tickets", "planes", "trains", "buses", "boats", "bikes", "maps", "globes", "cities", "countries", "worlds", "planets", "galaxies", "universes", "beaches", "forests", "parks", "schools", "hospitals", "restaurants", "stores", "museums", "libraries", "offices", "factories", "bridges", "roads", "paths", "skies", "earths", "winds", "rains", "snows", "ices", "fires", "waters", "stones", "woods", "metals", "music", "movies", "art", "dances", "sports", "teams", "ideas", "dreams", "plans", "reasons", "problems", "solutions", "questions", "answers", "stories", "poems", "letters", "messages", "secrets", "promises", "gifts", "toys", "tools", "machines", "plants", "animals", "people", "children", "men", "women", "kings", "queens", "princes", "princesses", "heroes", "villains"};
const char *verbs_singular[] = {"runs", "jumps", "sings", "drives", "grows", "sleeps", "eats", "reads", "writes", "plays", "flies", "swims", "thinks", "dreams", "works", "learns", "laughs", "cries", "talks", "walks", "looks", "sees", "hears", "touches", "feels", "tastes", "smells", "speaks", "listens", "waits", "hopes", "believes", "knows", "understands", "remembers", "forgets", "loves", "hates", "helps", "hurts", "gives", "takes", "finds", "loses", "makes", "breaks", "builds", "destroys", "opens", "closes", "starts", "stops", "turns", "changes", "chooses", "decides", "asks", "answers", "calls", "shows", "hides", "uses", "sells", "buys", "wins", "loses", "create", "destroy", "protect", "attack", "support", "oppose", "allow", "forbid", "encourage", "discourage", "agree", "disagree", "invite", "refuse", "prefer", "accept", "reject", "visit", "live", "die"};
const char *verbs_plural[] = {"run", "jump", "sing", "drive", "grow", "sleep", "eat", "read", "write", "play", "fly", "swim", "think", "dream", "work", "learn", "laugh", "cry", "talk", "walk", "look", "see", "hear", "touch", "feel", "taste", "smell", "speak", "listen", "wait", "hope", "believe", "know", "understand", "remember", "forget", "love", "hate", "help", "hurt", "give", "take", "find", "lose", "make", "break", "build", "destroy", "open", "close", "start", "stop", "turn", "change", "choose", "decide", "ask", "answer", "call", "show", "hide", "use", "sell", "buy", "win", "lose", "create", "destroy", "protect", "attack", "support", "oppose", "allow", "forbid", "encourage", "discourage", "agree", "disagree", "invite", "refuse", "prefer", "accept", "reject", "visit", "live", "die"};
const char *adverbs[] = {"quickly", "slowly", "loudly", "happily", "carefully", "sadly", "quietly", "easily", "well", "badly", "eagerly", "silently", "softly", "bravely", "mysteriously", "often", "rarely", "always", "never", "sometimes", "usually", "generally", "normally", "occasionally", "seldom", "frequently", "constantly", "continually", "regularly", "irregularly", "punctually", "late", "early", "soon", "now", "then", "later", "before", "after", "again", "once", "twice", "thrice", "mostly", "partially", "fully", "completely", "almost", "nearly", "totally", "slightly", "somewhat", "especially", "particularly", "surprisingly", "suddenly", "gradually", "eventually", "finally", "certainly", "probably", "possibly", "maybe", "perhaps", "definitely", "absolutely", "clearly", "obviously", "simply", "just", "merely", "only", "simply", "indeed", "actually", "really", "virtually", "practically", "technically", "literally", "figuratively", "approximately"};
const char *prepositions[] = {"on", "in", "under", "over", "by", "near", "with", "through", "around", "at", "above", "below", "beside", "behind", "between", "among", "across", "along", "towards", "from", "into", "onto", "out", "within", "without", "against", "beyond", "upon", "beneath", "during", "before", "after", "until", "since", "for"};
const char *conjunctions[] = {"and", "but", "or", "so", "because", "if", "although", "though", "while", "unless", "since", "as", "when", "where", "whenever", "wherever", "before", "after", "until", "once"};
const char *pronouns_singular[] = {"he", "she", "it"};
const char *pronouns_plural[] = {"they"};

// --- Sentence structures ---
const char *sentence_structures[] = {
    "[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Adverb].",
    "[Pronoun:subject] [Verb:subject] [Adverb] [Preposition] [Article:noun] [Noun].",
    "[Article:noun] [Noun:subject] [Verb:subject] [Conjunction] [Article:noun] [Noun:noun] [Verb:noun].",
    "[Pronoun:subject] [Verb:subject] [Article:noun] [Adjective] [Noun].",
     "[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Preposition] [Article:noun] [Noun:noun].",
     "[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Adverb] [Conjunction] [Article:noun] [Adjective] [Noun:noun] [Verb:noun].",
     "[Pronoun:subject] [Verb:subject] [Adverb] [Preposition] [Article:noun] [Adjective] [Noun].",
      "[Article:noun] [Adjective] [Noun:subject] [Verb:subject] [Preposition] [Article:noun] [Noun:noun] [Conjunction] [Article:noun] [Noun:noun] [Verb:noun]."
};
const int num_sentence_structures = sizeof(sentence_structures) / sizeof(sentence_structures[0]);


// --- Functions ---
char * generate_sentence() {
    static char sentence[MAX_SENTENCE_LENGTH];
    memset(sentence, 0, MAX_SENTENCE_LENGTH);

    const char *structure = sentence_structures[rand() % num_sentence_structures];

    int used_words[8][64] = {0}; // Tracks if a word has been used for a specific category
    int subjects[1] = {0}; // 0=undetermined, 1=singular, 2=plural

    int i;
    for (i = 0; structure[i] != '\0'; ++i)
    {
        if (structure[i] == '[')
        {
            int start = i + 1;
            int end = 0;
            for (int j = start; structure[j] != '\0'; ++j)
            {
                 if (structure[j] == ']')
                 {
                      end = j;
                      break;
                 }
            }
            if (end == 0) break; // Malformed structure, stop processing

            char key_type[20] = {0};
            char modifier[20] = {0};
            int k = 0; // Index of ':'
            for(int j = start; j < end; j++)
            {
                 if (structure[j] == ':')
                 {
                       k = j;
                       break;
                 }
                 key_type[j - start] = structure[j];
            }
           if (k) // If ':' was found
           {
              for (int j = k + 1; j < end; j++)
                modifier[j - k - 1] = structure[j];
           }
           else // No modifier, copy key_type as modifier for simpler logic later
           {
               strncpy(modifier, key_type, sizeof(modifier) - 1);
           }

            const char **word_list = NULL;
            int num_words = 0;
            int word_category_index = -1; // Index for used_words array

            // Determine word list and category index
            if (strcmp(key_type, "Article") == 0) {
                word_category_index = 0;
                if (strcmp(modifier, "noun") == 0) {
                    if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
                    word_list = (subjects[0] == 1) ? articles_singular : articles_plural;
                    num_words = (subjects[0] == 1) ? sizeof(articles_singular) / sizeof(articles_singular[0]) : sizeof(articles_plural) / sizeof(articles_plural[0]);
                } else {
                    word_list = articles_singular; // Default or unknown modifier
                    num_words = sizeof(articles_singular) / sizeof(articles_singular[0]);
                }
            } else if (strcmp(key_type, "Adjective") == 0) {
                word_category_index = 1;
                word_list = adjectives;
                num_words = sizeof(adjectives) / sizeof(adjectives[0]);
            } else if (strcmp(key_type, "Noun") == 0) {
                word_category_index = 2;
                if (strcmp(modifier, "subject") == 0) {
                    if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
                    word_list = (subjects[0] == 1) ? nouns_singular : nouns_plural;
                    num_words = (subjects[0] == 1) ? sizeof(nouns_singular) / sizeof(nouns_singular[0]) : sizeof(nouns_plural) / sizeof(nouns_plural[0]);
                } else if (strcmp(modifier, "noun") == 0) {
                    // Noun modifier implies it should match subject plurality if determined
                    if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
                    word_list = (subjects[0] == 1) ? nouns_singular : nouns_plural;
                    num_words = (subjects[0] == 1) ? sizeof(nouns_singular) / sizeof(nouns_singular[0]) : sizeof(nouns_plural) / sizeof(nouns_plural[0]);
                } else {
                     word_list = nouns_singular; // Default
                     num_words = sizeof(nouns_singular) / sizeof(nouns_singular[0]);
                }
            } else if (strcmp(key_type, "Verb") == 0) {
                 word_category_index = 3;
                 if (strcmp(modifier, "subject") == 0 || strcmp(modifier, "noun") == 0) { // Verb matches subject/noun
                     if(subjects[0] == 0) subjects[0] = rand() % 2 + 1;
                     word_list = (subjects[0] == 1) ? verbs_singular : verbs_plural;
                     num_words = (subjects[0] == 1) ? sizeof(verbs_singular) / sizeof(verbs_singular[0]) : sizeof(verbs_plural) / sizeof(verbs_plural[0]);
                 } else {
                     word_list = verbs_singular; // Default
                     num_words = sizeof(verbs_singular) / sizeof(verbs_singular[0]);
                 }
            } else if (strcmp(key_type, "Adverb") == 0) {
                 word_category_index = 4;
                 word_list = adverbs;
                 num_words = sizeof(adverbs) / sizeof(adverbs[0]);
            } else if (strcmp(key_type, "Preposition") == 0) {
                 word_category_index = 5;
                 word_list = prepositions;
                 num_words = sizeof(prepositions) / sizeof(prepositions[0]);
            } else if (strcmp(key_type, "Conjunction") == 0) {
                 word_category_index = 6;
                 word_list = conjunctions;
                 num_words = sizeof(conjunctions) / sizeof(conjunctions[0]);
            } else if (strcmp(key_type, "Pronoun") == 0) {
                 word_category_index = 7;
                 if (strcmp(modifier, "subject") == 0) {
                     if (subjects[0] == 0) subjects[0] = rand() % 2 + 1;
                     word_list = (subjects[0] == 1) ? pronouns_singular : pronouns_plural;
                     num_words = (subjects[0] == 1) ? sizeof(pronouns_singular) / sizeof(pronouns_singular[0]) : sizeof(pronouns_plural) / sizeof(pronouns_plural[0]);
                 } else {
                     word_list = pronouns_singular; // Default
                     num_words = sizeof(pronouns_singular) / sizeof(pronouns_singular[0]);
                 }
            }

            // If a valid word list was found
            if (word_list != NULL && num_words > 0 && word_category_index != -1) {
                int chosen_word_index = rand() % num_words;
                int attempts = 0; // Prevent infinite loop if all words used (unlikely)

                // Find an unused word for this category
                while(attempts < num_words) {
                    bool found = false;
                    for (int z = 0; z < 64; z++) {
                        if (used_words[word_category_index][z] == 0) break; // End of used list
                        if (used_words[word_category_index][z] == chosen_word_index + 1) {
                            found = true;
                            break;
                        }
                    }
                    if (!found) break; // Word is not used, exit while loop

                    // Word was used, try next one
                    chosen_word_index = (chosen_word_index + 1) % num_words;
                    attempts++;
                }

                // Mark the word as used for this category
                if (attempts < num_words) {
                     for(int z = 0; z < 64; z++) {
                        if (used_words[word_category_index][z] == 0) {
                           used_words[word_category_index][z] = chosen_word_index + 1;
                           break;
                         }
                      }
                }
                // else { // Fallback if all words somehow used
                //    chosen_word_index = rand() % num_words;
                // }


                const char* chosen_word = word_list[chosen_word_index];
                int len = strlen(chosen_word);
                int current_sentence_len = strlen(sentence);

                // Check if there's enough space for the word and potentially a space + null terminator
                if (MAX_SENTENCE_LENGTH - current_sentence_len - 1 >= len + 1) { // +1 for potential space or just null term
                    // Add a space BEFORE the word if:
                    // 1. Not the first word being added (current_sentence_len > 0).
                    // 2. The character *before* the opening bracket '[' in the template was a space.
                    if (current_sentence_len > 0 && i > 0 && structure[i - 1] == ' ') {
                         // Check space remaining *just* for the space
                         if (current_sentence_len < MAX_SENTENCE_LENGTH - 2) {
                            strcat(sentence, "  ");
                            current_sentence_len++; // Update length after adding space
                         } else {
                             break; // Not enough space even for the preceding space
                         }
                    }

                    // Add the word itself, checking space again in case only the space fit
                    if (MAX_SENTENCE_LENGTH - current_sentence_len - 1 >= len) {
                        strcat(sentence, chosen_word);
                    } else {
                        break; // Not enough space for the word
                    }

                } else {
                    // Not enough space, maybe truncate or stop
                    break; // Stop generating sentence if out of space initially
                }
            }
            i = end; // Move loop index past the processed placeholder
        }
        else if (structure[i] != ' ') { // Don't add spaces from template directly
            int current_len = strlen(sentence);
            // Remove trailing space before punctuation if present
             if (current_len > 0 && sentence[current_len - 1] == ' ' && (structure[i] == '.' || structure[i] == ',' || structure[i] == '!' || structure[i] == '?')) {
                 sentence[current_len - 1] = '\0'; // Remove trailing space
                 current_len--;
             }
            // Add the punctuation if space allows
            if (current_len < MAX_SENTENCE_LENGTH - 1) {
                sentence[current_len] = structure[i];
                sentence[current_len + 1] = '\0';
            } else {
                break; // Stop if no space for punctuation
            }
        }
        // Skip spaces in the template string, they are handled above based on context
    }

    // Capitalize the first letter
    if(strlen(sentence) > 0){
      sentence[0] = toupper(sentence[0]);
    }

    return sentence;
}


int main(void) {
    /* Initialize graphics */
    gfx_Begin();
    gfx_SetDrawBuffer();

    // --- Set colors ---
    gfx_SetTextFGColor(COLOR_BLACK); // Black text
    gfx_SetTextBGColor(COLOR_WHITE); // White background for text transparency
    gfx_SetColor(COLOR_WHITE);       // White color for fill

    gfx_SetTextConfig(gfx_text_noclip);
    gfx_FillScreen(COLOR_WHITE); // Clear screen to white background

    /* Initialize random seed based on real-time clock */
    srand(rtc_Time());

    char sentence[MAX_SENTENCE_LENGTH];
    strcpy(sentence, generate_sentence());

    kb_key_t key;
    int text_x, text_y;
    const uint8_t sentence_scale_x = 2;
    const uint8_t sentence_scale_y = 2;
    const int line_height = 8 * sentence_scale_y; // Base font height (8) * Y scale
    const int heading_y = 10;
    const int footer_y = GFX_LCD_HEIGHT - 20;
    const int sentence_start_y = heading_y + 20; // Start sentence below heading
    const int sentence_x_offset = 10; // <<<--- ADDED: Define the horizontal offset (e.g., 10 pixels)

    // Strings for header/footer
    const char *heading_text = "Sentence Generator";
    const char *footer_text = "Press ENTER to generate or CLEAR to leave";

    /* Main loop */
    while (true) {
         // Clear the buffer with white background before drawing
         gfx_FillScreen(COLOR_WHITE);

         // --- Draw Header and Footer (with default 1x1 scale) ---
         gfx_SetTextScale(1, 1);

         // Center and draw heading
         text_x = (GFX_LCD_WIDTH - gfx_GetStringWidth(heading_text)) / 2;
         gfx_PrintStringXY(heading_text, text_x, heading_y);

         // Center and draw footer
         text_x = (GFX_LCD_WIDTH - gfx_GetStringWidth(footer_text)) / 2;
         gfx_PrintStringXY(footer_text, text_x, footer_y);


         // --- Draw Generated Sentence (with 2x2 scale) ---
         gfx_SetTextScale(sentence_scale_x, sentence_scale_y);

         // Reset text position for drawing the sentence
         text_x = sentence_x_offset; // Start at the offset
         text_y = sentence_start_y; // Use calculated start Y
         gfx_SetTextXY(text_x, text_y);

         // Word wrapping logic
         int word_start_index = 0;
         for (int i = 0; sentence[i] != '\0'; ++i) {
            // Find the end of the current word (space or null terminator)
            if (sentence[i] == ' ' || sentence[i+1] == '\0') {
                int word_end_index = (sentence[i+1] == '\0') ? i + 1 : i; // Include last char if end of sentence
                char word[MAX_SENTENCE_LENGTH] = {0}; // Should be large enough for any single word
                strncpy(word, sentence + word_start_index, word_end_index - word_start_index);

                // Include the space after the word for width calculation, unless it's the very end
                char word_with_space[MAX_SENTENCE_LENGTH + 1] = {0};
                strcpy(word_with_space, word);
                if (sentence[i] == ' ') {
                    strcat(word_with_space, "  ");
                }

                // Get width using the current scale (2x2)
                int word_width = gfx_GetStringWidth(word_with_space);

                // Check if the word fits on the current line
                if (text_x + word_width >= GFX_LCD_WIDTH) {
                    // Doesn't fit, move to the next line
                    text_x = sentence_x_offset;
                    text_y += line_height; // Use scaled line height
                    gfx_SetTextXY(text_x, text_y);

                    // Check if we're drawing off the screen (below the footer)
                     if (text_y >= footer_y - line_height) {
                         break; // Stop drawing if off screen / overlaps footer
                     }
                }

                // Print the word (without the trailing space used for width calc)
                gfx_PrintString(word);

                 // Print the space if it exists
                if (sentence[i] == ' ') {
                    gfx_PrintChar(' ');
                }

                // Update text position and word start index for the next word
                text_x = gfx_GetTextX();
                word_start_index = i + 1;
            }
         }

        // Swap the buffer to the screen
        gfx_BlitBuffer();

        // Handle key presses
        kb_Scan();
        key = kb_Data[6]; // Check group 6 for Enter and Clear

        if (key & kb_Enter) {
            // Generate a new sentence
            strcpy(sentence, generate_sentence());
            // Small delay to prevent multiple generations from one press
            delay(150);
        }
        if (key & kb_Clear) {
            break; // Exit loop
        }
    }

    /* End graphics */
    gfx_End();

    return 0;
}

Download Here:https://drive.google.com/file/d/1ZMDvgwvTPKxbco7htAkbQhUeqlx2yfIy/view?usp=sharing
To screenshot you can run it in CEmu and use the Capture functions to produce either still or animated screenshots.
Great! I'll try that. Before I was trying to use the connection app directly to my calculator, but it just says that it's not connected.
You can also try using TiLP II if you think it's a problem with TI Connect rather than your calculator itself. It has the ability to capture your calculator screen so long as it's connected to your computer and recognized by the program.

Also, if you're able to get some screenshots you could upload your program to the Archives or ticalc.org. That way, people can review your creation and you can easily push updates as they're built.

I've yet to try the program but I'll let you know what I think of it when I get around to it. I see potential for some rudimentary conversational skills to be added to this; maybe by using a similar deconstruction of the English language for parsing user text, one could make a quaint, comically nonsensical chatbot like good old Cleverbot was... although, fortunately not as deterministic and not as cheaty (I recall Cleverbot using prefabricated responses over dynamically generated ones).
I was using Tilp anyway because I'm using linux, and TI Connect wasn't available. But I was able to get the ROM image from my calculator and get screenshots.
CarJeepTruckson wrote:
Great! I'll try that. Before I was trying to use the connection app directly to my calculator, but it just says that it's not connected.
When a C or assembly program is running, the background components that allow TI Connect CE to speak to your calculator are generally not available, unless you explicitly make them so.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement