Four Letter Word generator based on an associative word dictionary.

Dependencies:   _24LCXXX

Dependents:   vfd_modular_clock_mbed

Four Letter Word generator based on an associative word dictionary.

Needs an EEPROM to function (can be programmed onto a 24LC512 I2C EEPROM, or available as a pre-programmed add-on board)

Comes with a censored mode that removes expletives as well as a fully uncensored mode.

For details see:

Committer:
Backstrom
Date:
Fri Feb 20 09:59:01 2015 +0000
Revision:
4:706c5fa05343
Parent:
0:4d3dec05a4b7
Child:
5:8748fd0dce7c
Bugfix, seed can not be 0, so add 1 to seed.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Backstrom 0:4d3dec05a4b7 1 /*
Backstrom 0:4d3dec05a4b7 2 * Four Letter Word Generator
Backstrom 0:4d3dec05a4b7 3 * (C) 2015 Akafugu Corporation
Backstrom 0:4d3dec05a4b7 4 *
Backstrom 0:4d3dec05a4b7 5 * This program is free software; you can redistribute it and/or modify it under the
Backstrom 0:4d3dec05a4b7 6 * terms of the GNU General Public License as published by the Free Software
Backstrom 0:4d3dec05a4b7 7 * Foundation; either version 2 of the License, or (at your option) any later
Backstrom 0:4d3dec05a4b7 8 * version.
Backstrom 0:4d3dec05a4b7 9 *
Backstrom 0:4d3dec05a4b7 10 * This program is distributed in the hope that it will be useful, but WITHOUT ANY
Backstrom 0:4d3dec05a4b7 11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
Backstrom 0:4d3dec05a4b7 12 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Backstrom 0:4d3dec05a4b7 13 *
Backstrom 0:4d3dec05a4b7 14 */
Backstrom 0:4d3dec05a4b7 15
Backstrom 0:4d3dec05a4b7 16 /*
Backstrom 0:4d3dec05a4b7 17 * To use this Four Letter Word generator you will need the following:
Backstrom 0:4d3dec05a4b7 18 *
Backstrom 0:4d3dec05a4b7 19 * - A 512kbit/64kb I2C EEPROM
Backstrom 0:4d3dec05a4b7 20 * - A database file, generated from this Processing application:
Backstrom 0:4d3dec05a4b7 21 * https://github.com/perjg/fourletterword
Backstrom 0:4d3dec05a4b7 22 * - A method for uploading the data file to the EEPROM
Backstrom 0:4d3dec05a4b7 23 * (Either an Arduino Mega, or a normal Arduino with a micro SD card)
Backstrom 0:4d3dec05a4b7 24 */
Backstrom 0:4d3dec05a4b7 25
Backstrom 0:4d3dec05a4b7 26 #include <string.h>
Backstrom 0:4d3dec05a4b7 27 #include "flw.h"
Backstrom 0:4d3dec05a4b7 28 #include "flw_blacklist.h"
Backstrom 0:4d3dec05a4b7 29
Backstrom 0:4d3dec05a4b7 30
Backstrom 0:4d3dec05a4b7 31 #define EEPROM_ADDR 0b1010000
Backstrom 0:4d3dec05a4b7 32
Backstrom 0:4d3dec05a4b7 33 void FourLetterWord::rot13(char* w)
Backstrom 0:4d3dec05a4b7 34 {
Backstrom 0:4d3dec05a4b7 35 while (*w != '\0') {
Backstrom 0:4d3dec05a4b7 36 if (*w >= 'A' && *w <= 'M') {
Backstrom 0:4d3dec05a4b7 37 *w += 13;
Backstrom 0:4d3dec05a4b7 38 }
Backstrom 0:4d3dec05a4b7 39 else if (*w >= 'N' && *w <= 'Z') {
Backstrom 0:4d3dec05a4b7 40 *w -= 13;
Backstrom 0:4d3dec05a4b7 41 }
Backstrom 0:4d3dec05a4b7 42
Backstrom 0:4d3dec05a4b7 43 w++;
Backstrom 0:4d3dec05a4b7 44 }
Backstrom 0:4d3dec05a4b7 45 }
Backstrom 0:4d3dec05a4b7 46
Backstrom 0:4d3dec05a4b7 47 bool FourLetterWord::binary_search(const char *key, int imin, int imax)
Backstrom 0:4d3dec05a4b7 48 {
Backstrom 0:4d3dec05a4b7 49 int pos;
Backstrom 0:4d3dec05a4b7 50 int cond = 0;
Backstrom 0:4d3dec05a4b7 51 char buf[5];
Backstrom 0:4d3dec05a4b7 52
Backstrom 0:4d3dec05a4b7 53 while (imin <= imax) {
Backstrom 0:4d3dec05a4b7 54 pos = (imin+imax) / 2;
Backstrom 0:4d3dec05a4b7 55
Backstrom 0:4d3dec05a4b7 56 strcpy(buf, flw_blacklist[pos]);
Backstrom 0:4d3dec05a4b7 57 rot13(buf);
Backstrom 0:4d3dec05a4b7 58 cond = strcmp(key, buf);
Backstrom 0:4d3dec05a4b7 59
Backstrom 0:4d3dec05a4b7 60 if (cond == 0) return true;
Backstrom 0:4d3dec05a4b7 61 else if (cond>0) imin = pos+1;
Backstrom 0:4d3dec05a4b7 62 else imax = pos-1;
Backstrom 0:4d3dec05a4b7 63 }
Backstrom 0:4d3dec05a4b7 64
Backstrom 0:4d3dec05a4b7 65 return false;
Backstrom 0:4d3dec05a4b7 66 }
Backstrom 0:4d3dec05a4b7 67
Backstrom 0:4d3dec05a4b7 68
Backstrom 0:4d3dec05a4b7 69 uint8_t FourLetterWord::read_byte(unsigned int addr) {
Backstrom 0:4d3dec05a4b7 70 uint8_t rdata = 0xFF;
Backstrom 0:4d3dec05a4b7 71
Backstrom 0:4d3dec05a4b7 72 _24lc.nbyte_read(addr, &rdata, 1);
Backstrom 0:4d3dec05a4b7 73 return rdata;
Backstrom 0:4d3dec05a4b7 74 }
Backstrom 0:4d3dec05a4b7 75
Backstrom 0:4d3dec05a4b7 76 void FourLetterWord::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
Backstrom 0:4d3dec05a4b7 77 _24lc.nbyte_read(addr, buffer, length);
Backstrom 0:4d3dec05a4b7 78 }
Backstrom 0:4d3dec05a4b7 79
Backstrom 0:4d3dec05a4b7 80
Backstrom 0:4d3dec05a4b7 81 void FourLetterWord::begin(uint32_t seed, bool censored)
Backstrom 0:4d3dec05a4b7 82 {
Backstrom 4:706c5fa05343 83 m_lfsr = seed + 1;
Backstrom 0:4d3dec05a4b7 84 m_censored = censored;
Backstrom 0:4d3dec05a4b7 85 }
Backstrom 0:4d3dec05a4b7 86
Backstrom 0:4d3dec05a4b7 87 uint32_t FourLetterWord::randomize()
Backstrom 0:4d3dec05a4b7 88 {
Backstrom 0:4d3dec05a4b7 89 // http://en.wikipedia.org/wiki/Linear_feedback_shift_register
Backstrom 0:4d3dec05a4b7 90 // Galois LFSR: taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
Backstrom 0:4d3dec05a4b7 91 m_lfsr = (m_lfsr >> 1) ^ (-(m_lfsr & 1u) & 0xD0000001u);
Backstrom 0:4d3dec05a4b7 92 return m_lfsr;
Backstrom 0:4d3dec05a4b7 93 }
Backstrom 0:4d3dec05a4b7 94
Backstrom 0:4d3dec05a4b7 95 bool FourLetterWord::hasEeprom()
Backstrom 0:4d3dec05a4b7 96 {
Backstrom 0:4d3dec05a4b7 97 uint8_t b1 = read_byte(0);
Backstrom 0:4d3dec05a4b7 98 uint8_t b2 = read_byte(1);
Backstrom 0:4d3dec05a4b7 99
Backstrom 0:4d3dec05a4b7 100 if (b1 == 65 && b2 == 66)
Backstrom 0:4d3dec05a4b7 101 return true;
Backstrom 0:4d3dec05a4b7 102 return false;
Backstrom 0:4d3dec05a4b7 103 }
Backstrom 0:4d3dec05a4b7 104
Backstrom 0:4d3dec05a4b7 105 char* FourLetterWord::get_word_censored()
Backstrom 0:4d3dec05a4b7 106 {
Backstrom 0:4d3dec05a4b7 107 char* w = get_word_uncensored();
Backstrom 0:4d3dec05a4b7 108
Backstrom 0:4d3dec05a4b7 109 // assume a maximum of 5 censored words chosen in a row
Backstrom 0:4d3dec05a4b7 110 for (uint8_t i = 0; i < 5; i++) {
Backstrom 0:4d3dec05a4b7 111 if (binary_search(w, 0, BLACKLIST_SIZE)) { // censored
Backstrom 0:4d3dec05a4b7 112 w = get_word_uncensored();
Backstrom 0:4d3dec05a4b7 113 }
Backstrom 0:4d3dec05a4b7 114 else
Backstrom 0:4d3dec05a4b7 115 return w;
Backstrom 0:4d3dec05a4b7 116 }
Backstrom 0:4d3dec05a4b7 117
Backstrom 0:4d3dec05a4b7 118 return w;
Backstrom 0:4d3dec05a4b7 119 }
Backstrom 0:4d3dec05a4b7 120
Backstrom 0:4d3dec05a4b7 121 char* FourLetterWord::get_word_uncensored()
Backstrom 0:4d3dec05a4b7 122 {
Backstrom 0:4d3dec05a4b7 123 unsigned char low = 0xFF, high = 0xFF;
Backstrom 0:4d3dec05a4b7 124 unsigned char count = 0;
Backstrom 0:4d3dec05a4b7 125 int next = 0;
Backstrom 0:4d3dec05a4b7 126
Backstrom 0:4d3dec05a4b7 127 read_buffer(m_offset, (uint8_t*)m_current_word, 5);
Backstrom 0:4d3dec05a4b7 128 count = m_current_word[4];
Backstrom 0:4d3dec05a4b7 129 m_current_word[4] = '\0';
Backstrom 0:4d3dec05a4b7 130
Backstrom 0:4d3dec05a4b7 131 next = randomize() % count;
Backstrom 0:4d3dec05a4b7 132 m_offset += 5 + next * 2;
Backstrom 0:4d3dec05a4b7 133
Backstrom 0:4d3dec05a4b7 134 high = read_byte(m_offset++);
Backstrom 0:4d3dec05a4b7 135 low = read_byte(m_offset++);
Backstrom 0:4d3dec05a4b7 136
Backstrom 0:4d3dec05a4b7 137 m_offset = (high << 8) | low;
Backstrom 0:4d3dec05a4b7 138
Backstrom 0:4d3dec05a4b7 139 return m_current_word;
Backstrom 0:4d3dec05a4b7 140 }
Backstrom 0:4d3dec05a4b7 141
Backstrom 0:4d3dec05a4b7 142 char* FourLetterWord::getWord()
Backstrom 0:4d3dec05a4b7 143 {
Backstrom 0:4d3dec05a4b7 144 if (m_censored) return get_word_censored();
Backstrom 0:4d3dec05a4b7 145 return get_word_uncensored();
Backstrom 0:4d3dec05a4b7 146 }