PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/moul/x/daily/asciiart/v1

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v1
Namespace
moul / x / daily / asciiart
Files
4 (README)(gnomod.toml)
Exported functions
6
Module
gno.land/r/moul/x/daily/asciiart/v1
gno
0.9

Files (4)

  • README.mdmarkdown
  • gnomod.tomltoml
  • asciiart.gnogno
  • asciiart_test.gnogno
asciiart.gnogno
1// Package asciiart is a small on-chain ASCII art generator. Instead of a2// hand-authored font table, each pattern is produced by a short, pure,3// deterministic algorithm -- e.g. the Sierpinski triangle falls out of a4// single bitwise AND over row/column indices. Callers pick a pattern and a5// size; the realm renders it and keeps a gallery of everyone's generations.6package asciiart78import (9	"strconv"10	"strings"1112	"chain"13	"chain/runtime"1415	"gno.land/p/moul/kit/ui/v0"16	"gno.land/p/moul/kit/store/v0"17)1819// maxSize bounds every pattern's size parameter so a single Generate call20// can't blow the block gas limit on a pathologically large grid.21const maxSize = 322223// galleryPageSize caps how many pieces Render shows on the home page.24const galleryPageSize = 82526// piece carries no ID field: the id belongs to the store, which hands it back27// on lookup and iteration.28type piece struct {29	Pattern   string30	Size      int31	Author    address32	CreatedAt int6433	Art       string34}3536// gallery assigns the piece ids. v1 kept its own nextID plus a padID() that37// zero-padded to width 6, the narrowest ceiling in this repo: at the millionth38// piece the padding stops and the gallery starts rendering out of order. The39// store key is 8 fixed bytes with no width to outgrow.40var gallery = store.Named("piece")4142// RenderDiamond draws a filled diamond of half-width n (2n-1 rows total),43// each row's stars centered and padded with spaces.44func RenderDiamond(n int) string {45	if n < 1 {46		panic("diamond size must be >= 1")47	}48	var b strings.Builder49	for i := 0; i < 2*n-1; i++ {50		d := i51		if i >= n {52			d = 2*n - 2 - i53		}54		b.WriteString(strings.Repeat(" ", n-1-d))55		b.WriteString(strings.Repeat("*", 2*d+1))56		if i < 2*n-2 {57			b.WriteString("\n")58		}59	}60	return b.String()61}6263// RenderPyramid draws a solid triangle n rows tall, widening by two stars64// per row and centered with leading spaces.65func RenderPyramid(n int) string {66	if n < 1 {67		panic("pyramid size must be >= 1")68	}69	var b strings.Builder70	for i := 0; i < n; i++ {71		b.WriteString(strings.Repeat(" ", n-1-i))72		b.WriteString(strings.Repeat("*", 2*i+1))73		if i < n-1 {74			b.WriteString("\n")75		}76	}77	return b.String()78}7980// RenderSierpinski draws a Sierpinski triangle in an n x n grid (n must be a81// power of two): cell (row, col) is filled exactly when row&col == 0, the82// classic bitwise identity for Pascal's-triangle-mod-2.83func RenderSierpinski(n int) string {84	if n < 1 || n&(n-1) != 0 {85		panic("sierpinski size must be a power of two (1, 2, 4, 8, 16, 32)")86	}87	var b strings.Builder88	for row := 0; row < n; row++ {89		for col := 0; col < n; col++ {90			if row&col == 0 {91				b.WriteString("#")92			} else {93				b.WriteString(" ")94			}95		}96		if row < n-1 {97			b.WriteString("\n")98		}99	}100	return b.String()101}102103// RenderChecker draws an n x n checkerboard of # and . cells.104func RenderChecker(n int) string {105	if n < 1 {106		panic("checker size must be >= 1")107	}108	var b strings.Builder109	for row := 0; row < n; row++ {110		for col := 0; col < n; col++ {111			if (row+col)%2 == 0 {112				b.WriteString("#")113			} else {114				b.WriteString(".")115			}116		}117		if row < n-1 {118			b.WriteString("\n")119		}120	}121	return b.String()122}123124func renderPattern(pattern string, size int) string {125	switch pattern {126	case "diamond":127		return RenderDiamond(size)128	case "pyramid":129		return RenderPyramid(size)130	case "sierpinski":131		return RenderSierpinski(size)132	case "checker":133		return RenderChecker(size)134	default:135		panic(`unknown pattern: use "diamond", "pyramid", "sierpinski", or "checker"`)136	}137}138139// Generate renders a pattern, adds it to the on-chain gallery, and returns140// the rendered art.141func Generate(cur realm, pattern string, size int) string {142	if size < 1 || size > maxSize {143		panic("size must be between 1 and " + strconv.Itoa(maxSize))144	}145	art := renderPattern(pattern, size)146147	author := cur.Previous().Address()148	id := gallery.Add(&piece{149		Pattern:   pattern,150		Size:      size,151		Author:    author,152		CreatedAt: runtime.ChainHeight(),153		Art:       art,154	})155156	chain.Emit("ArtGenerated", "id", id.String(), "pattern", pattern, "author", author.String())157158	return art159}160161func renderHome() string {162	var b strings.Builder163	b.WriteString("# ASCII Art Generator\n\n")164	b.WriteString("Four deterministic patterns, no font table required -- each shape " +165		"falls out of a short formula over row/column indices. Pick a pattern and a " +166		"size (1-" + strconv.Itoa(maxSize) + ", sierpinski wants a power of two) and " +167		"`Generate` adds it to the gallery below.\n\n")168	b.WriteString("## Patterns\n\n")169	b.WriteString("- `diamond` -- filled diamond, half-width `size`\n")170	b.WriteString("- `pyramid` -- solid triangle, `size` rows tall\n")171	b.WriteString("- `sierpinski` -- Sierpinski gasket in an n×n grid " +172		"(`row & col == 0`), `size` a power of two\n")173	b.WriteString("- `checker` -- n×n checkerboard\n\n")174	b.WriteString("Call `Generate(pattern, size)`. View a piece at this realm's path " +175		"plus its ID (e.g. `.../asciiart:3`).\n\n")176177	b.WriteString("## Gallery (total: " + gallery.LastID().String() + ")\n\n")178	if gallery.Len() == 0 {179		b.WriteString("_nothing generated yet -- be the first_\n")180		return b.String()181	}182183	// The newest page, straight from the store: no counter, and only that184	// window is walked.185	for _, e := range gallery.PageReverse(1, galleryPageSize) {186		p := e.Value.(*piece)187		b.WriteString("### #" + e.ID.String() + " -- " + p.Pattern + " (size " + strconv.Itoa(p.Size) + ")\n\n")188		b.WriteString("by `" + p.Author.String() + "` at block " + strconv.Itoa(int(p.CreatedAt)) + "\n\n")189		b.WriteString("```\n" + p.Art + "\n```\n\n")190	}191	return b.String()192}193194func renderPiece(idStr string) string {195	safe := ui.Inline(idStr)196	id, ok := store.ParseID(idStr)197	if !ok {198		return "# Piece " + safe + "\n\nNo such piece.\n"199	}200	v, ok := gallery.Get(id)201	if !ok {202		return "# Piece #" + safe + "\n\nNo such piece.\n"203	}204	p := v.(*piece)205206	var b strings.Builder207	b.WriteString("# Piece #" + id.String() + "\n\n")208	b.WriteString("- Pattern: " + p.Pattern + "\n")209	b.WriteString("- Size: " + strconv.Itoa(p.Size) + "\n")210	b.WriteString("- Author: `" + p.Author.String() + "`\n")211	b.WriteString("- Block: " + strconv.Itoa(int(p.CreatedAt)) + "\n\n")212	b.WriteString("```\n" + p.Art + "\n```\n")213	return b.String()214}215216// Render shows the pattern guide + gallery at "", or one piece by numeric ID.217func Render(path string) string {218	path = strings.TrimPrefix(strings.TrimSpace(path), "/")219	if path == "" {220		return renderHome()221	}222	return renderPiece(path)223}224

Functions

  • Generate(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, pattern string, size int) string

  • Render(path string) string

  • RenderChecker(n int) string

  • RenderDiamond(n int) string

  • RenderPyramid(n int) string

  • RenderSierpinski(n int) string

Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

Rendered

RenderedRawgnoweb ↗

vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.