Transaction

D3F723F1234C31…F778B9A7ACC8

Block 26,087 · index 0 · indexed

Summary

Hash
D3F723F1234C31E6BE442DA7792F8BA9FF0042C3EEAC44DB772AF778B9A7ACC8
Block
26,087
Size
7945 bytes
Gas used
12,590,214 / 15,108,316
Fee
1000000ugnot
Memo
gnopublish
Status
success

Messages

#1AddPackagegno.land/r/moul/x/daily/memory/v09 arguments

Arguments · 9

  1. #1memory
  2. #2README.md
  3. #3# 🧠 Memory Match > ⚠️ **Experimental — generated with no human supervision.** This realm was > produced automatically by an MCP-driven agent to exercise the gno MCP server > and tooling, and to generate test content for gno compilers, linters and > formatters. **Not audited. Not for production.** Full context & folder README: > [r/moul/x/daily](https://github.com/moul/gno-contracts/blob/main/r/moul/x/daily/README.md) --- A concentration game on a 4x4 grid of 8 emoji pairs. The board is shuffled deterministically from the current block height (there is no on-chain RNG), so every `NewGame` produces a reproducible layout for a given height. Flip tiles two at a time: matching pairs stay face-up, mismatches flip back on your next move. The realm tracks your move count and matched pairs and reports the solved state. **Realm path:** `gno.land/r/REPLACE_ADDR/memory` ## How to play - `Flip(index int)` — reveal the tile at `index` (0–15, row-major). The first reveal starts an attempt; the second completes a *move*. Matching faces stay up; a mismatch shows both tiles until your next `Flip` clears them. - `NewGame()` — reshuffle the board using the current block height as the seed. - `Render(path)` — renders the grid (❓ hidden, emoji revealed/matched), the move count, matched-pair count, and whether the game is solved. ## Example calls ``` # start a fresh, height-seeded board NewGame() # reveal cell 0, then cell 5 Flip(0) Flip(5) # view the board gnokey query vm/qrender --data "gno.land/r/REPLACE_ADDR/memory:" ``` Solve all 8 pairs to win; the render then shows your total move count. <!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) --> --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. > 🧪 **Highly experimental — potentially vibe-coded.** Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md). <!-- END GNOCONTRACTS FOOTER -->
  4. #4gnomod.toml
  5. #5module = "gno.land/r/moul/x/daily/memory/v0" gno = "0.9"
  6. #6memory.gno
  7. #7// Package memory implements "Memory Match", a concentration game on a // 4x4 grid of 8 emoji pairs. The board is shuffled deterministically from // the current block height (no on-chain RNG exists), so a NewGame started at // a given height always produces the same layout. package memory import ( "strconv" "strings" "chain" "chain/runtime" ) const gridSize = 16 // 4x4 const numPairs = 8 // faces are the 8 distinct emoji; each appears exactly twice on the board. var faces = [numPairs]string{"🐶", "🐱", "🦊", "🐸", "🐵", "🐼", "🦁", "🐧"} // tile holds the face index (0..7) for a cell and whether it is matched. type tile struct { face int matched bool } // board is the full game state. It is a package-level singleton so the realm // persists a single shared game. var board = struct { tiles [gridSize]tile flipped []int // indices currently face-up but not yet resolved (0, 1 or 2) moves int // number of completed two-tile attempts pairs int // matched pairs so far height int64 // block height the current game was seeded from started bool }{} // shuffle produces a deterministic permutation of the 16 tile faces from a // 64-bit seed. It fills a slice with two of each face index then applies a // Fisher-Yates shuffle driven by a simple LCG — fully deterministic, no RNG. func shuffle(seed int64) [gridSize]tile { vals := make([]int, 0, gridSize) for i := 0; i < numPairs; i++ { vals = append(vals, i, i) } // LCG (Numerical Recipes constants); force unsigned-style math via uint64. state := uint64(seed)*6364136223846793005 + 1442695040888963407 for i := len(vals) - 1; i > 0; i-- { state = state*6364136223846793005 + 1442695040888963407 j := int(state % uint64(i+1)) vals[i], vals[j] = vals[j], vals[i] } var out [gridSize]tile for i := 0; i < gridSize; i++ { out[i] = tile{face: vals[i], matched: false} } return out } func ensureStarted() { if !board.started { reset(runtime.ChainHeight()) } } func reset(height int64) { board.tiles = shuffle(height) board.flipped = nil board.moves = 0 board.pairs = 0 board.height = height board.started = true } // NewGame reshuffles the board using the current block height as the seed. func NewGame(cur realm) { reset(runtime.ChainHeight()) chain.Emit("NewGame", "height", strconv.FormatInt(board.height, 10)) } // Flip reveals the tile at index (0..15). // // Rules: // - If two tiles are already showing from a previous unmatched attempt, // this Flip first clears them (they turn back to hidden), then reveals // the requested tile as the first of a new attempt. // - Revealing the second tile of an attempt completes a move: matching // faces stay face-up (matched); a mismatch leaves both showing until the // next Flip clears them. // - Flipping an already-matched or already-showing tile is rejected. func Flip(cur realm, index int) { ensureStarted() if index < 0 || index >= gridSize { panic("index out of range") } if board.tiles[index].matched { panic("tile already matched") } // A completed unmatched attempt (2 face-up, non-matching) is cleared // before the next reveal. if len(board.flipped) == 2 { board.flipped = nil } for _, f := range board.flipped { if f == index { panic("tile already flipped") } } board.flipped = append(board.flipped, index) if len(board.flipped) != 2 { chain.Emit("Flip", "index", strconv.Itoa(index)) return } // Second tile of the attempt: resolve. board.moves++ a, b := board.flipped[0], board.flipped[1] if board.tiles[a].face == board.tiles[b].face { board.tiles[a].matched = true board.tiles[b].matched = true board.pairs++ board.flipped = nil chain.Emit("Match", "index", strconv.Itoa(index), "pairs", strconv.Itoa(board.pairs)) } else { // leave both showing; next Flip clears them chain.Emit("Miss", "index", strconv.Itoa(index)) } } func solved() bool { return board.pairs == numPairs } // cellFace returns the emoji to display for a cell given the current state. func cellFace(i int) string { if board.tiles[i].matched { return faces[board.tiles[i].face] } for _, f := range board.flipped { if f == i { return faces[board.tiles[i].face] } } return "❓" } // Render draws the board as Markdown: a 4x4 grid, move count and solved state. func Render(path string) string { ensureStarted() var sb strings.Builder sb.WriteString("# 🧠 Memory Match\n\n") sb.WriteString("Match all 8 emoji pairs on the 4x4 grid.\n\n") sb.WriteString("| | | | |\n") sb.WriteString("|:-:|:-:|:-:|:-:|\n") for row := 0; row < 4; row++ { sb.WriteString("|") for col := 0; col < 4; col++ { sb.WriteString(" " + cellFace(row*4+col) + " |") } sb.WriteString("\n") } sb.WriteString("\n") sb.WriteString("- Moves: **" + strconv.Itoa(board.moves) + "**\n") sb.WriteString("- Pairs matched: **" + strconv.Itoa(board.pairs) + " / " + strconv.Itoa(numPairs) + "**\n") sb.WriteString("- Seed height: **" + strconv.FormatInt(board.height, 10) + "**\n\n") if solved() { sb.WriteString("🎉 **Solved in " + strconv.Itoa(board.moves) + " moves!** Call `NewGame` to play again.\n") } else { sb.WriteString("Call `Flip(index)` with a cell index 0–15. `NewGame()` reshuffles.\n") } return sb.String() }
  8. #8/gno.MemPackageType
  9. #9 MPUserProd

Result log

msg:0,success:true,log:,events:[]

← Back to block 26,087