ThoML
1/13/2008 10:58:00 PM
Two basic ASCII front-ends are provided. If figlet is available and
the
script is run with the -f command line option, you get a slightly
more
appealing visualization of the cards. Otherwise only the card names
are
displayed.
Command-line options:
quiz152 [TIME=2] [CARDS=2] [DECKS=4] [MAXSTEP=10]
- pause between deals
- max cards displayed simultaneously
- number of decks
- after max steps, users are asked to make their guess
Thomas.
#!/usr/bin/env ruby
# Author:: Thomas Link (micathom AT gmail com)
# Created:: 2008-01-11.
module Quiz152; end
class Quiz152::Game
NAMES = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
VALUES = [1] * 6 + [0, 0] + [-1] * 5
SUITS = ['c', 'd', 'h', 's']
def initialize(ui, time=2, cardn=2, decks=4, maxstep=10)
@ui = ui.new(self)
@time = time
@msgtime = 1
@cardn = cardn
@maxstep = maxstep
cards = NAMES.zip(VALUES)
@cards = SUITS.inject([]) {|a, s| a += cards.map{|c| c.dup
<< s}} * decks
@decks = decks
@count = 4 - 4 * decks
end
def run
@ui.message "Decks: #@decks",
"Pause: #{@time}s",
"Cards at a time: 1-#@cardn",
"Ready? (Press ENTER)"
@ui.input
while deal(rand(@maxstep) + 1)
break unless query_count
end
@ui.message "Bye!"
end
def deal(n)
n.times do
@ui.deal_new
(1 + rand(@cardn)).times do |i|
cname, cvalue, csuit =
@cards.delete_at(rand(@cards.size))
if cname
@ui.deal_card(i, cname, csuit)
@count += cvalue
else
@ui.message('This is the end.')
return false
end
end
@ui.deal_show
sleep @time
end
return true
end
def query_count
@ui.clear
@ui.message 'Your guess:'
count = @ui.input.chomp
if ['q', 'x', 'bye', 'exit', 'quit'].include?(count)
return false
else
case count.to_i
when 0
@ui.message "The current count is #@count."
when @count
@ui.message "Well."
else
@ui.message "It's always a pleasure playing with you.
(count: #@count)"
end
sleep @msgtime
return true
end
end
end
class Quiz152::TextUI
def initialize(game)
@game = game
clear
end
def message(*text)
text.each {|t| puts t}
end
def input
STDIN.gets
end
def clear
100.times {puts "\n"}
end
def deal_card(nth, name, suit)
@output << [name]
end
def deal_new
@output = []
clear
end
def deal_show
@output.transpose.each do |lines|
puts lines.join(' ')
end
puts
end
end
class Quiz152::Figlet < Quiz152::TextUI
def initialize(*args)
super
@t_card = <<'CARD'
__________________
/ | |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
\__________________/
CARD
@t_suit = {
'c' => <<'SUIT',
_
_/ \_
/ \_/ \_/^\_/
/_SUIT
'd' => <<'SUIT',
/ / \ /
\/
SUIT
'h' => <<'SUIT',
_ _
/ \/ \ /
\ /
\/
SUIT
's' => <<'SUIT',
__
/ | |
\_/\_/
/__SUIT
}
end
def deal_card(nth, name, suit)
card = @t_card.dup.split("\n")
fill_card(card, @t_suit[suit], 3, 2)
fill_card(card, `figlet -k "#{name}"`, 8, 8)
@output << card
end
def fill_card(template, text, x0, y0)
text.each_with_index do |l, i|
template[i + y0][x0 .. (x0 + l.size - 2)] = l.chomp
end
template
end
end
if __FILE__ == $0
ui = Quiz152::TextUI
loop do
case ARGV[0]
when '-h', '--help'
puts "#$0 [TIME=2] [CARDS=2] [DECKS=4] [MAXSTEP=10]"
exit 1
when '-f', '--figlet'
ui = Quiz152::Figlet
ARGV.shift
else
break
end
end
Quiz152::Game.new(ui, *ARGV.map{|e| e.to_i}).run
end