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:

Revision:
0:4d3dec05a4b7
Child:
2:ff0163bc298d
Child:
4:706c5fa05343
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flw.cpp	Tue Feb 10 09:53:03 2015 +0000
@@ -0,0 +1,146 @@
+/*
+ * Four Letter Word Generator
+ * (C) 2015 Akafugu Corporation
+ *
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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.
+ *
+ */
+
+/*
+ * To use this Four Letter Word generator you will need the following:
+ *
+ * - A 512kbit/64kb I2C EEPROM
+ * - A database file, generated from this Processing application:
+ *   https://github.com/perjg/fourletterword
+ * - A method for uploading the data file to the EEPROM
+ *   (Either an Arduino Mega, or a normal Arduino with a micro SD card)
+ */
+
+#include <string.h>
+#include "flw.h"
+#include "flw_blacklist.h"
+
+
+#define EEPROM_ADDR 0b1010000
+
+void FourLetterWord::rot13(char* w)
+{
+    while (*w != '\0') {
+        if (*w >= 'A' && *w <= 'M') {
+            *w += 13;
+        }
+        else if (*w >= 'N' && *w <= 'Z') {
+            *w -= 13;
+        }
+
+      w++;
+    }
+}
+
+bool FourLetterWord::binary_search(const char *key, int imin, int imax)
+{
+  int pos;
+  int cond = 0;
+  char buf[5];
+
+  while (imin <= imax) {
+    pos = (imin+imax) / 2;
+    
+    strcpy(buf, flw_blacklist[pos]);
+    rot13(buf);
+    cond = strcmp(key, buf);
+    
+    if (cond == 0)   return true;
+    else if (cond>0) imin = pos+1;
+    else             imax = pos-1;
+  }
+  
+  return false;
+}
+
+
+uint8_t FourLetterWord::read_byte(unsigned int addr) {
+  uint8_t rdata = 0xFF;
+  
+  _24lc.nbyte_read(addr, &rdata, 1);
+  return rdata;
+}
+
+void FourLetterWord::read_buffer(unsigned int addr, uint8_t *buffer, int length) {
+  _24lc.nbyte_read(addr, buffer, length);
+}
+
+
+void FourLetterWord::begin(uint32_t seed, bool censored)
+{
+  m_lfsr = seed;
+  m_censored = censored;
+}
+
+uint32_t FourLetterWord::randomize()
+{
+  // http://en.wikipedia.org/wiki/Linear_feedback_shift_register
+  // Galois LFSR: taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */
+  m_lfsr = (m_lfsr >> 1) ^ (-(m_lfsr & 1u) & 0xD0000001u);
+  return m_lfsr;  
+}
+
+bool FourLetterWord::hasEeprom()
+{
+   uint8_t b1 = read_byte(0); 
+   uint8_t b2 = read_byte(1); 
+   
+   if (b1 == 65 && b2 == 66)
+     return true;
+   return false;
+}
+
+char* FourLetterWord::get_word_censored()
+{
+  char* w = get_word_uncensored();
+  
+  // assume a maximum of 5 censored words chosen in a row
+  for (uint8_t i = 0; i < 5; i++) {
+    if (binary_search(w, 0, BLACKLIST_SIZE)) { // censored
+      w = get_word_uncensored();
+    }
+    else
+      return w;
+  }
+  
+  return w;
+}
+
+char* FourLetterWord::get_word_uncensored()
+{
+  unsigned char low = 0xFF, high = 0xFF;
+  unsigned char count = 0;
+  int next = 0;
+
+  read_buffer(m_offset, (uint8_t*)m_current_word, 5);
+  count = m_current_word[4];
+  m_current_word[4] = '\0';
+
+  next = randomize() % count;
+  m_offset += 5 + next * 2;
+
+  high = read_byte(m_offset++);
+  low  = read_byte(m_offset++);
+
+  m_offset = (high << 8) | low;
+
+  return m_current_word;
+}
+
+char* FourLetterWord::getWord()
+{
+  if (m_censored) return get_word_censored();
+  return get_word_uncensored();
+}