Public Access
Game of Life page element and built-in page
A new page element runs Conway's Game of Life in an area (the whole display by default), one per page. Start: random dots, one pattern, or the icons whose names start with a text in turn or in random order. Edges: wrap around, dead, or a hidden margin where gliders fly out of view (leftovers that stay put in the margin are cleared, so a glider gun runs cleanly). It restarts when the board is still or repeats within 16 generations and/or after a number of generations, after a hold time (an empty board at once). logic/life holds the board and timing (tested), display/life_player runs the board of the shown page, ticked before each frame; frames are paced like scrolling text. The element reuses existing fields, so the page format stays the same. The Icons tab has a library of 17 LifeWiki patterns (checked with a simulation), and the built-in page "Game of Life" shuffles through the life_ icons. About 12 KB flash, 8 KB RAM. Version 2.17.0, tested on the display over OTA. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
948087077d
commit
a91d2550d7
29 files changed
+1402
-31
No files matched your search
@@ -3,14 +3,17 @@
|
||||
#include <Arduino.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "logic/life.h"
|
||||
#include "logic/settings.h"
|
||||
|
||||
static const char *const TYPES[] = {"clock", "date", "ha", "text", "countdown", "stopwatch", "image", "bar"};
|
||||
static const char *const TYPES[] = {"clock", "date", "ha", "text", "countdown", "stopwatch", "image", "bar", "life"};
|
||||
static const char *const ALIGNS[] = {"left", "center", "right"};
|
||||
static const char *const OVERLAYS[] = {"top", "box", "invert"};
|
||||
static const char *const LANGUAGES[] = {"nl", "en"};
|
||||
static const char *const SHOWS[] = {"number", "duration", "time", "map"};
|
||||
static const char *const UNITS[] = {"s", "min", "h"};
|
||||
// Game of Life (in input_unit, see logic/page.h)
|
||||
static const char *const LIFE_STARTS[] = {"random", "pattern", "rotate", "shuffle"};
|
||||
|
||||
template <size_t N> static int indexOf(const char *const (&names)[N], const char *name)
|
||||
{
|
||||
@@ -66,7 +69,12 @@ void pageToJson(const DynamicPage &page, JsonObject out)
|
||||
formatTarget(e.target, target);
|
||||
o["target"] = String(target);
|
||||
o["show"] = SHOWS[(int)e.show];
|
||||
o["input_unit"] = UNITS[e.input_unit];
|
||||
o["input_unit"] = UNITS[e.input_unit < UNIT_COUNT ? e.input_unit : 0];
|
||||
if (e.type == ElementType::Life)
|
||||
{
|
||||
o["start"] = LIFE_STARTS[e.input_unit < LIFE_START_COUNT ? e.input_unit : 0];
|
||||
o["generations"] = e.target;
|
||||
}
|
||||
o["auto_unit"] = e.auto_unit;
|
||||
o["absolute"] = e.absolute;
|
||||
o["map"] = withDegrees(e.map);
|
||||
@@ -148,6 +156,14 @@ const char *pageFromJson(JsonVariantConst in, DynamicPage &page)
|
||||
const char *target = o["target"] | "";
|
||||
if (e.type == ElementType::Countdown && !parseTarget(target, e.target))
|
||||
return "Countdown: enter a date and time";
|
||||
if (e.type == ElementType::Life)
|
||||
{
|
||||
int start = indexOf(LIFE_STARTS, o["start"] | "random");
|
||||
if (start < 0)
|
||||
return "Game of Life: unknown start";
|
||||
e.input_unit = start;
|
||||
e.target = constrain(o["generations"] | 0.0, 0.0, (double)LIFE_GENERATIONS_MAX + 1);
|
||||
}
|
||||
if (!copyText(o["font"], e.font, sizeof(e.font)) || !copyText(o["text"], e.text, sizeof(e.text)) ||
|
||||
!copyText(o["suffix"], e.suffix, sizeof(e.suffix)) || !copyText(o["entity"], e.entity, sizeof(e.entity)) ||
|
||||
!copyText(o["attribute"], e.attribute, sizeof(e.attribute)))
|
||||
|
||||
Reference in new issue
Block a user