Module: PWN::Banner

Defined in:
lib/pwn/banner.rb,
lib/pwn/banner/anon.rb,
lib/pwn/banner/ninja.rb,
lib/pwn/banner/bubble.rb,
lib/pwn/banner/matrix.rb,
lib/pwn/banner/pirate.rb,
lib/pwn/banner/jmp_esp.rb,
lib/pwn/banner/radare2.rb,
lib/pwn/banner/cheshire.rb,
lib/pwn/banner/code_cave.rb,
lib/pwn/banner/f_society.rb,
lib/pwn/banner/fork_bomb.rb,
lib/pwn/banner/dont_panic.rb,
lib/pwn/banner/radare2_ai.rb,
lib/pwn/banner/off_the_air.rb,
lib/pwn/banner/white_rabbit.rb

Overview

Static banners and pure, PWN-branded retro ASCII/color loops: falling_blocks, snake, pong, and asteroids. mini_frame returns fresh rows on a borderless canvas; use equal width and height (5..16) for complete square artwork. Dimensions clamp to 0..16 (colored blocks: 0..64). Set branding: false for an unbranded pane with the wordmark row reclaimed for play; tiny panes then stay blank. The caller samples mini_names once per session and advances the explicit frame index every mini_frame_seconds(name:) (0.05 for Pong/Asteroids, 0.1 otherwise). mini_cells replays 1800 seeded gameplay frames (MINI_FRAME_COUNT); mini_frame retains its legacy 60-frame ASCII loop. These are decorative game simulations, not interactive games or telemetry. mini_cells uses local Random.new with seed 73 by default; callers may keep a different integer seed per session. Six immutable replays are cached. Tetrominoes stack and clear; snake pursues food and grows; Pong rallies include imperfect paddle tracking, misses and score pips between serves. Blocks use horizontal half-cells with independent foreground/background colors, filling the pane below PWN (up to 64 cells). Other games retain quadrant pixels; snake stays centered with food/head color priority. White line-clear flashes and game-over/reset wipes are intentional. Pong uses half-cell motion and one-cell-high paddles without speeding up play. Asteroids uses five-pixel cyan arrowheads on a half-cell grid, sparse small white rocks, yellow shots and red thrust; wrapped collisions split real rocks. Static Banner modules autoload only when needed. For more information, see: http://www.rubyinside.com/ruby-techniques-revealed-autoload-1652.html

Defined Under Namespace

Modules: Anon, Bubble, Cheshire, CodeCave, DontPanic, FSociety, ForkBomb, JmpEsp, Matrix, Ninja, OffTheAir, Pirate, Radare2, Radare2AI, WhiteRabbit

Constant Summary collapse

MINI_WIDTH =

Bounded, square character canvases. The caller owns the surrounding border.

16
MINI_HEIGHT =
16
MINI_FRAME_SECONDS =
0.1
MINI_FRAME_COUNT =
1800
MINI_SEED =
73
MINI_CACHE_LIMIT =
6
MINI_ASCII_FRAME_COUNT =
60
MINI_SHIP =

Five quadrant pixels, not a scaled-down vector sprite. Eight stable headings keep the nose legible even in the 5-column pane; physics still turns smoothly.

Array.new(8) do |heading|
  points = heading.even? ? [[-1, -1], [0, -1], [1, 0], [0, 1], [-1, 1]] : [[0, -1], [1, 0], [1, 1], [0, 1], [-1, 0]]
  (heading / 2).times { points = points.map { |x, y| [-y, x] } }
  points.map(&:freeze).freeze
end.freeze
MINI_PIXELS =

Compact replay pixels expand to fresh cells only at the API boundary.

{
  ' ' => [' ', :blue], 'P' => ['P', :blue], 'W' => ['W', :blue], 'N' => ['N', :blue],
  'c' => ['█', :cyan], 'y' => ['█', :yellow], 'm' => ['█', :magenta],
  'b' => ['█', :blue], 'r' => ['█', :red], 'g' => ['█', :green],
  'w' => ['█', :white], 'f' => ['▄', :red], 'o' => ['▀', :yellow],
  'l' => ['▌', :cyan], 'q' => ['▐', :magenta], ':' => ['░', :blue]
}.merge(%i[cyan magenta yellow white green red blue].each_with_index.flat_map do |color, index|
  ' ▘▝▀▖▌▞▛▗▚▐▜▄▙▟█'.chars.each_with_index.map do |glyph, mask|
    [(256 + (index * 16) + mask).chr(Encoding::UTF_8), [glyph, color]]
  end
end.to_h).merge(%i[black cyan magenta yellow white green red blue].each_with_index.flat_map do |top, top_index|
  %i[black cyan magenta yellow white green red blue].each_with_index.map do |bottom, bottom_index|
    mask = (top == :black ? 0 : 3) | (bottom == :black ? 0 : 12)
    cell = if top == bottom
             [top == :black ? ' ' : '█', top, :black]
           elsif top == :black
             ['▄', bottom, :black]
           else
             ['▀', top, bottom]
           end
    [(1024 + (((top_index * 8) + bottom_index) * 16) + mask).chr(Encoding::UTF_8), cell]
  end
end.to_h).transform_values(&:freeze).freeze
MINI_SHAPES =
[
  [[0, 0], [1, 0], [2, 0], [3, 0]],
  [[0, 0], [1, 0], [0, 1], [1, 1]],
  [[0, 0], [1, 0], [2, 0], [1, 1]],
  [[0, 0], [0, 1], [1, 1], [2, 1]],
  [[2, 0], [0, 1], [1, 1], [2, 1]],
  [[1, 0], [2, 0], [0, 1], [1, 1]],
  [[0, 0], [1, 0], [1, 1], [2, 1]]
].map { |shape| shape.map(&:freeze).freeze }.freeze

Class Method Summary collapse

Class Method Details

.authors ⇒ Object

Author(s)

0day Inc. [email protected]



805
806
807
808
809
# File 'lib/pwn/banner.rb', line 805

public_class_method def self.authors
  "AUTHOR(S):
    0day Inc. <[email protected]>
  "
end

.get(opts = {}) ⇒ Object

Supported Method Parameters

PWN::Banner.get( index: 'optional - defaults to random banner index' )



746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
# File 'lib/pwn/banner.rb', line 746

public_class_method def self.get(opts = {})
  index = opts[:index].to_i
  index = Random.rand(1..15) unless index.positive?

  banner = ''
  case index
  when 1
    banner = PWN::Banner::Anon.get
  when 2
    banner = PWN::Banner::Bubble.get
  when 3
    banner = PWN::Banner::Cheshire.get
  when 4
    banner = PWN::Banner::CodeCave.get
  when 5
    banner = PWN::Banner::DontPanic.get
  when 6
    banner = PWN::Banner::ForkBomb.get
  when 7
    banner = PWN::Banner::FSociety.get
  when 8
    banner = PWN::Banner::JmpEsp.get
  when 9
    banner = PWN::Banner::Matrix.get
  when 10
    banner = PWN::Banner::Ninja.get
  when 11
    banner = PWN::Banner::OffTheAir.get
  when 12
    banner = PWN::Banner::Pirate.get
  when 13
    banner = PWN::Banner::Radare2.get
  when 14
    banner = PWN::Banner::Radare2AI.get
  when 15
    banner = PWN::Banner::WhiteRabbit.get
  else
    raise 'Invalid Index.'
  end

  banner
end

.help ⇒ Object

Display Usage for this Module



813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
# File 'lib/pwn/banner.rb', line 813

public_class_method def self.help
  puts "USAGE:
    # Run get and return its result
    #{self}.get(
      index: 'optional - defaults to random banner index'
    )

    # List compact animation names; sample once per session, not per redraw.
    #{self}.mini_names

    # Presentation cadence for colored games; ASCII keeps MINI_FRAME_SECONDS.
    #{self}.mini_frame_seconds(
      name: 'optional - animation name, defaults to falling_blocks'
    )

    # Return fresh ASCII rows; caller owns timing, theme, and terminal drawing.
    # Decorative retro loops, not interactive games or progress/telemetry.
    # Advance every MINI_FRAME_SECONDS (0.1 seconds); ASCII wraps at 60.
    # Pass equal width and height for a square; complete artwork fits 5..16.
    # No border is included. Smaller panes show only a clipped PWN wordmark.
    #{self}.mini_frame(
      name: 'optional - falling_blocks, snake, pong, or asteroids; defaults to falling_blocks',
      frame: 'optional - integer frame index, defaults to zero and wraps at 60',
      width: 'optional - columns clamped to zero through 16; defaults to 16',
      height: 'optional - rows clamped to zero through 16; defaults to 16',
      branding: 'optional - include the legacy wordmark, defaults to true; false reclaims its row'
    )

    # Return fresh Unicode block cells: { glyph:, foreground:, background: }.
    # Colors are standard terminal names; blocks may use colored backgrounds.
    # No ANSI or IO. Other games retain black backgrounds.
    # 1800 frames; mini_frame_seconds is 0.05 for Pong/Asteroids, 0.1 otherwise.
    # Caller samples mini_names once per session. No timers or animation threads.
    # Seeded gameplay, bounded six-replay cache; white hold/wipe marks resets.
    # Square refers to terminal cells, not physical pixels. Caller owns borders.
    #{self}.mini_cells(
      name: 'optional - falling_blocks, snake, pong, or asteroids; defaults to falling_blocks',
      frame: 'optional - integer frame index, defaults to zero and wraps at 1800',
      width: 'optional - columns clamped to 0..64 for blocks, 0..16 otherwise; defaults to 16',
      height: 'optional - rows clamped to 0..64 for blocks, 0..16 otherwise; defaults to 16',
      seed: 'optional - integer local PRNG seed, defaults to 73; retain per session',
      branding: 'optional - include the legacy wordmark, defaults to true; false reclaims its row'
    )

    # Run welcome and return its result
    #{self}.welcome

    # Print the AUTHOR(S) string for this module.
    #{self}.authors
  "
  constants.sort
end

.mini_cells(opts = {}) ⇒ Object

Supported Method Parameters

Return rows of single-column Unicode block cells, with named terminal colors. Each fresh cell has glyph, foreground and background keys; no ANSI or IO. Square means terminal-cell dimensions, not physical pixels. Caller owns borders. Use mini_frame_seconds for cadence; 1800 frames span 90 or 180 seconds. Colored blocks fill the canvas with half-cell pieces; other games cap at 16. PWN::Banner.mini_cells( name: 'optional - falling_blocks, snake, pong, or asteroids; defaults to falling_blocks', frame: 'optional - integer index, defaults to zero and wraps at 1800', width: 'optional - columns clamped to 0..64 for blocks, 0..16 otherwise; defaults to 16', height: 'optional - rows clamped to 0..64 for blocks, 0..16 otherwise; defaults to 16', seed: 'optional - integer local PRNG seed, defaults to 73; retain per session', branding: 'optional - include the legacy wordmark, defaults to true; false reclaims its row' )

Raises:

  • (ArgumentError)


163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/pwn/banner.rb', line 163

public_class_method def self.mini_cells(opts = {})
  name = (opts[:name] || :falling_blocks).to_s
  phase = (opts[:frame] || 0).to_i % MINI_FRAME_COUNT
  raise ArgumentError, "Unknown mini-banner: #{name}" unless mini_names.map(&:to_s).include?(name)

  limit = name == 'falling_blocks' ? 64 : MINI_WIDTH
  width = (opts[:width] || MINI_WIDTH).to_i.clamp(0, limit)
  height = (opts[:height] || MINI_HEIGHT).to_i.clamp(0, limit)
  return [] if width.zero? || height.zero?

  branding = opts[:branding] != false
  # Simulate one extra row before removing the legacy label, so every output
  # row belongs to gameplay without changing the public dimension limits.
  rows = if width < 5 || height < 5
           [branding ? 'PWN'[0, width].center(width) : ' ' * width] + Array.new(height - 1) { ' ' * width }
         else
           replay = mini_replay(name: name, width: width, height: height + (branding ? 0 : 1), seed: (opts[:seed] || MINI_SEED).to_i)
           branding ? replay[phase][:rows] : replay[phase][:rows].drop(1)
         end
  rows.map do |row|
    row.chars.map do |pixel|
      glyph, foreground, background = MINI_PIXELS.fetch(pixel)
      { glyph: glyph.dup, foreground: foreground, background: background || :black }
    end
  end
end

.mini_frame(opts = {}) ⇒ Object

Supported Method Parameters

Return fresh ASCII rows for decorative retro loops, not interactive games. Use equal width and height for a square; 5..16 retains the complete artwork. Smaller panes degrade to a wordmark. Caller owns randomness, clock and IO. PWN::Banner.mini_frame( name: 'optional - falling_blocks, snake, pong, or asteroids; defaults to falling_blocks', frame: 'optional - integer frame index, defaults to zero and wraps at 60', width: 'optional - output columns clamped to zero through 16, defaults to 16', height: 'optional - output rows clamped to zero through 16, defaults to 16', branding: 'optional - include the legacy wordmark, defaults to true; false reclaims its row' )

Raises:

  • (ArgumentError)


106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/pwn/banner.rb', line 106

public_class_method def self.mini_frame(opts = {})
  name = (opts[:name] || :falling_blocks).to_s
  raise ArgumentError, "Unknown mini-banner: #{name}" unless mini_names.map(&:to_s).include?(name)

  phase = (opts[:frame] || 0).to_i % MINI_ASCII_FRAME_COUNT
  width = (opts[:width] || MINI_WIDTH).to_i.clamp(0, MINI_WIDTH)
  height = (opts[:height] || MINI_HEIGHT).to_i.clamp(0, MINI_HEIGHT)
  return [] if width.zero? || height.zero?

  branding = opts[:branding] != false
  return Array.new(height) { ' ' * width } if !branding && (width < 5 || height < 5)

  height += 1 unless branding
  rows = Array.new(height) { ' ' * width }
  rows[0] = 'PWN'[0, width].center(width)
  return rows if width < 5 || height < 5

  send("mini_#{name}", rows: rows, phase: phase, width: width, height: height)
  branding ? rows : rows.drop(1)
end

.mini_frame_seconds(opts = {}) ⇒ Object

Supported Method Parameters

Return the presentation interval; simulations preserve their gameplay speed. PWN::Banner.mini_frame_seconds( name: 'optional - animation name, defaults to falling_blocks' )

Raises:

  • (ArgumentError)


141
142
143
144
145
146
# File 'lib/pwn/banner.rb', line 141

public_class_method def self.mini_frame_seconds(opts = {})
  name = (opts[:name] || :falling_blocks).to_s
  raise ArgumentError, "Unknown mini-banner: #{name}" unless mini_names.map(&:to_s).include?(name)

  %w[pong asteroids].include?(name) ? 0.05 : MINI_FRAME_SECONDS
end

.mini_names ⇒ Object

Supported Method Parameters

List animation names; callers may sample once and retain the session choice. PWN::Banner.mini_names



131
132
133
# File 'lib/pwn/banner.rb', line 131

public_class_method def self.mini_names
  %i[falling_blocks snake pong asteroids]
end

.welcome ⇒ Object

Supported Method Parameters

PWN::Banner.get( index: 'optional - defaults to random banner index' )



794
795
796
797
798
799
800
801
# File 'lib/pwn/banner.rb', line 794

public_class_method def self.welcome
  banner = PWN::Banner.get
  banner = "#{banner}\nUse the #help command & methods for more options.\n"
  banner = "#{banner}e.g help\n"
  banner = "#{banner}e.g PWN.help\n"
  banner = "#{banner}e.g PWN::Plugins.help\n"
  banner = "#{banner}e.g PWN::Plugins::TransparentBrowser.help\n"
end