RosettaCodeData/Task/Matrix-digital-rain/Nim/matrix-digital-rain.nim
2023-07-01 13:44:08 -04:00

67 lines
1.7 KiB
Nim

import os, random, sequtils
import ncurses
const RowDelay = 40 # In milliseconds.
proc exit() {.noconv.} =
endwin()
quit QuitSuccess
proc run() =
const
Chars = "0123456789" # Characters to randomly appear in the rain sequence.
let stdscr = initscr()
noEcho()
cursSet(0)
startColor()
initPair(1, COLOR_GREEN, COLOR_BLACK)
attron(COLOR_PAIR(1).cint)
var width, height: cint
stdscr.getmaxyx(height, width)
let maxX = width - 1
let maxY = height - 1
# Create arrays of columns based on screen width.
# Array containing the current row of each column.
# Set top row as current row for all columns.
var columnsRow = repeat(cint -1, width)
# Array containing the active status of each column.
# A column draws characters on a row when active.
var columnsActive = newSeq[bool](width)
setControlCHook(exit)
while true:
for i in 0..maxX:
if columnsRow[i] == -1:
# If a column is at the top row, pick a random starting row and active status.
columnsRow[i] = cint(rand(maxY))
columnsActive[i] = bool(rand(1))
# Loop through columns and draw characters on rows.
for i in 0..maxX:
if columnsActive[i]:
# Draw a random character at this column's current row.
let charIndex = rand(Chars.high)
mvprintw(columnsRow[i], i, "%c", Chars[charIndex])
else:
# Draw an empty character if the column is inactive.
mvprintw(columnsRow[i], i, " ")
inc columnsRow[i]
# When a column reaches the bottom row, reset to top.
if columnsRow[i] > maxY: columnsRow[i] = -1
# Randomly alternate the column's active status.
if rand(999) == 0: columnsActive[i] = not columnsActive[i]
sleep(RowDelay)
refresh()
run()