#!/usr/bin/env ruby # frozen_string_literal: true require 'curses' require 'optparse' require 'minehunt' def display_curses( field, state = { dead: false, victory: false }, theme = { explorer: '()', dead_explorer: '☠ ', door: '=>', mine: '<>', cell: '██', visited_cell: ' ' } ) Curses.setpos 0, 0 if state[:dead] Curses.addstr "You blew up!!, score: #{field.score} " elsif state[:victory] Curses.addstr "You won!! :), score: #{field.score} " else Curses.addstr "Near #{field.count_nearby_mines} mines, score: #{field.score}" end field.height.times do |y| Curses.setpos y + 2, 0 field.width.times do |x| if [field.explorer_x, field.explorer_y] == [x, y] Curses.addstr state[:dead] ? theme[:dead_explorer] : theme[:explorer] elsif [field.width, field.height] == [x + 1, y + 1] Curses.addstr theme[:door] elsif field.field[[x, y]].open Curses.addstr theme[:visited_cell] elsif field.field[[x, y]].mine && ( state[:dead] || state[:victory] ) Curses.addstr theme[:mine] else Curses.addstr theme[:cell] end end end Curses.refresh end def ncurses_main( number_of_mines ) field = MineHunt::Board.new( number_of_mines ) finished = false Curses.init_screen Curses.cbreak Curses.noecho Curses.stdscr.keypad = true at_exit do Curses.close_screen end display_curses( field ) loop do direction = '' ch = Curses.getch if finished begin case ch when 'r' field = MineHunt::Board.new( number_of_mines ) finished = false else break end rescue Curses::RequestDeniedError 'prout' end else begin case ch when '1' direction = 'down-left' when '2', Curses::KEY_DOWN direction = 'down' when '3' direction = 'down-right' when '4', Curses::KEY_LEFT direction = 'left' when '6', Curses::KEY_RIGHT direction = 'right' when '7' direction = 'up-left' when '8', Curses::KEY_UP direction = 'up' when '9' direction = 'up-right' when 'q' break end rescue Curses::RequestDeniedError 'prout' end end state = field.move( direction ) finished = state[:dead] || state[:victory] display_curses( field, state ) end exit! end options = { number_of_mines: 20 } OptionParser.new do |opts| opts.banner = 'Usage: minehunt ' opts.on( '-m', '--mines INT' ) do |nb_mines| options[:number_of_mines] = nb_mines.to_i end end .parse! ncurses_main( options[:number_of_mines] )