Skip to content

Instantly share code, notes, and snippets.

@judesamp
Last active August 29, 2015 13:58
Show Gist options
  • Save judesamp/10014979 to your computer and use it in GitHub Desktop.
Save judesamp/10014979 to your computer and use it in GitHub Desktop.
A horse racing game for the terminal
class Game
attr_accessor :user_horse, :opponent_horse_1, :opponent_horse_2
def initialize
@goad_count = 0
@song_count = 0
@whisper_count = 0
@corner_counter = 1
@race_distances = [100, 125, 150]
@printer = PrintTrack.new
@race_strategies = ["fast", "slow", "the middle way"]
@race_sections = [
{section_name: "down the opening straightaway"},
{section_name: "approaching the first corner"},
{section_name: "corner"},
{section_name: "breaking out of the first corner"},
{section_name: "approaching the second corner"},
{section_name: "corner"},
{section_name: "breaking out of the second corner"},
{section_name: "approaching the third corner"},
{section_name: "corner"},
{section_name: "breaking out of the third corner"},
{section_name: "approaching the final corner"},
{section_name: "corner"},
{section_name: "the stretch"},
]
#Does @all_opponents need to be in Horses?
@all_opponents = [
[{name: "Stewball", base_speed: 4, stamina: 4, song: "I bet on the grey mare,\nI bet on the bay\nIf I'd have bet on ol' Stewball,\nI'd be a free man today. "}, {name: "Molly", base_speed: 5, stamina: 8, song: "Run Molly, run\n(Oh, Molly)\nRun Molly, run\nLong John's gonna beat you\nBeneath the shinin' sun"}],
[{name: "Appaloosa", base_speed: 6, stamina: 7, song: "Appaloosa, runnin’ wild in the dead of the night\nAppaloosa, you’re the message of love and light."}, {name: "Wildfire", base_speed: 7, stamina: 6, song: "She comes down from Yellow Mountain.\nOn a dark, flat land she rides.\nOn a pony she named Wildfire.\nWith a whirlwind by her side\nOn a cold Nebraska night"}],
[{name: "Bottle of Smoke", base_speed: 8, stamina: 9, song: "Thanks and praises\nThanks to Jesus\nI bet on the bottle of smoke \nI went to hell\nAnd to the races\nTo bet on the bottle of smoke"}, {name: "Feitlebaum", base_speed: 9, stamina: 6, song: "# It's a beautiful day for the race.\nStu Chan is the favorite today,\nAssault is in there,\nDog Biscuit is three to one,\nSafety Pin has been scratched, (ha ha)\nand at twenty to one: Feitlebaum."}]
]
measure_terminal_window
@user_horse = prepare_user_horse
process_pregame
process_race
#process_postgame
end
############ prerace
def process_pregame
clear_screen
print_welcome
set_horse_name
prompt_user_to_begin
choose_race
create_track
ask_for_opponent_horses(@race_type)
choose_strategy
introduce_race
#prepare_race
end
def print_welcome
puts ' __ __ ___ _ ___ ____ _ _ ___ _____ ____ _____ _ _ ___ ____ _ ___ ___ ___ '
puts ' ) (_) () __() | / _(/ __ \) \_/ () __( )__ __(/ __ \ )__ __() () () __( / _ \ )_\ / _() __( ( _( '
puts " \\ _ /| _) | (__ ))_ ))__((| _ || _) | | ))__(( | | | -- || _) ) ' / /( )\\ ))_ | _) _) \\ "
puts ' )/ \( )___()____(\__(\____/)_( )_()___( )_( \____/ )_( )_()_()___( |_()_\)_/ \_(\__()___()____) '
puts ' '
end
def set_horse_name
puts "In order to race today, you'll need to register your horse. What is your horse's name?"
horse_name = ""
until horse_name_valid?(horse_name)
puts "Please enter a horse name greater than one letter and less than 12.\n\n"
horse_name = gets.chomp
end
@user_horse.name = horse_name
end
def horse_name_valid?(horse_name)
horse_name.length > 0 && horse_name.length < 12
end
def prompt_user_to_begin
puts "\nOkay, thank you for signing up for the race. I hope you're ready to ride!\n\n"
end
def choose_race
puts "Would you like to race in a (1) Claiming race (the amateurs), (2) an Allowance race (the semi-pro), or (3) a Stakes race (the major leagues)?\n\n"
race = 0
until race_valid?(race)
puts "Please enter a 1, 2, or 3 to continue."
@race_type = gets.chomp
end
@race_type = @race_type.to_i
@race_type -= 1
end
def race_valid?(race_num)
@race_type == "1" || @race_type == "2" || @race_type == "3"
end
def create_track
@track = Track.new
@track.distance = @race_distances[@race_type]
end
def ask_for_opponent_horses(race_type)
num = race_type.to_i
num -= 1
@opponent_horses = []
@all_opponents[num].each do |horse_data|
horse = Horse.new(horse_data)
@opponent_horses.push(horse)
end
@opponent_horse_1 = @opponent_horses[0]
@opponent_horse_2 = @opponent_horses[1]
end
def prepare_user_horse
@user_horse = UserHorse.new
end
def choose_strategy
puts "\n\nOne last step and you're ready to race! You need to choose a race strategy. You can:\n\n"
puts "1. Go out fast and try to hang on to your lead (if you ever have one)!"
puts "2. Go out slow and hope to finish strong, catching all of your opponents in the last half mile"
puts "3. Stay in the middle of the pack and hope everything breaks your way.\n\n"
print "Well, don't just sit there, make a choice! "
@race_strategy = ''
until race_strategy_valid?(@race_strategy)
puts "Enter a 1, 2, or 3 to continue.\n\n"
@race_strategy = gets.chomp
end
@race_strategy = @race_strategy.to_i - 1
@race_strategy = @race_strategies[@race_strategy]
end
def race_strategy_valid?(strategy_num)
strategy_num == "1" || strategy_num == "2" || strategy_num =="3"
end
def introduce_race
# clear_screen
# puts "insert race and horse intros!"
end
######## race #########
def process_race
start_race
12.times do |count|
@printer.process_print(count+1, self)
run_race_section
end
finish_race
end
def start_race
race_countdown
#calculate_start bonus
calculate_progress
adjust_stamina
# race_section = retrieve_race_section
# issue_report(race_section[:section_name])
# jockey_action = get_jockey_action(race_section)
# process_jockey_action(jockey_action)
# @printer.process_print(0, self)
end
def race_countdown
clear_screen
puts "Okay, we're ready for the start. Horses into the gate!"
sleep 2
clear_screen
puts "3"
sleep 1
clear_screen
puts "2"
sleep 1
clear_screen
puts "1"
sleep 1
clear_screen
puts "And they're off..."
sleep 1
clear_screen
end
def calculate_progress
@user_horse.progress += @user_horse.run
@opponent_horse_1.progress += @opponent_horse_1.run
@opponent_horse_2.progress += @opponent_horse_2.run
# puts "#{@user_horse.name}: #{@user_horse.base_speed}"
# puts "#{@opponent_horse_1.name}: #{@opponent_horse_1.base_speed}"
# puts "#{@opponent_horse_2.name}: #{@opponent_horse_2.base_speed}\n\n"
end
#put in horse
def adjust_stamina
if @race_strategy == "fast"
unless @user_horse.stamina < 6
@user_horse.stamina -= 1
end
elsif @race_strategy == "slow"
@user_horse.stamina += 1 unless @user_horse.stamina > 9
else
return
end
end
def issue_report(race_section)
leader = calculate_leader
second = "calculeate second"
third = "calculate third"
if race_section == "corner"
puts "And they're in corner #{@corner_counter}. Looks like #{leader} is in the lead."
else
puts "And they're #{race_section}. Looks like #{leader} is in the lead.\n\n"
end
# puts different statements based on distance behind
end
def run_race_section
race_section = retrieve_race_section
calculate_progress
adjust_stamina
issue_report(race_section[:section_name])
jockey_action = get_jockey_action(race_section)
process_jockey_action(jockey_action)
sleep 1
if race_section[:section_name] == "corner"
@corner_counter += 1
end
end
# def run_corner
# # leader = "calculate leader"
# # calculate_progress
# # race_section = retrieve_race_section
# # if race_section[:section_name] == "skip"
# # return
# # end
# # issue_report(race_section[:section_name])
# # get_corner_strategy
# # @corner_counter += 1
# end
def finish_race
system 'clear'
print "And down the stretch they come. To the finish line... "
sleep 2
system 'clear'
puts
@printer.process_print(13, self)
print "\n\nIt's #{calculate_leader} at the wire!\n\n"
end
def get_jockey_action(race_section)
if race_section[:section_name] == "down the opening straightaway"
puts "You have three ways to motivate your horse. You can (1) Pinch your horse, (2) Whisper to Your horse, or (3) Sing to Your Horse. Which would you like to do?"
print '> '
else
puts "Would you like to pinch your horse (1), whisper to your horse (2), or sing to your horse (3)?"
end
jockey_action = ''
until jockey_action_valid?(jockey_action)
puts "Enter a 1, 2, or 3 to continue."
print '> '
jockey_action = gets.chomp
end
jockey_action.to_i
end
def jockey_action_valid?(action_num)
action_num == "1" || action_num == "2" || action_num =="3"
end
def process_jockey_action(jockey_action)
if jockey_action == 1
puts "You chose to pinch your horse!"
@goad_count += 1
if @goad_count < 4
@user_horse.base_speed += 1 unless @user_horse.base_speed > 8
elsif @goad_count >= 4
@user_horse.base_speed -=1 unless @user_horse.base_speed < 5
end
elsif jockey_action == 2
@whisper_count += 1
puts @whisper_count
puts "You chose to whisper to your horse!"
if @whisper_count > 2 && @whisper_count < 6
@user_horse.base_speed += 1
elsif @whisper_count > 5
@user_horse.stamina -= 1
else
return
end
else
puts "You chose to sing to your horse!"
@song_count += 1
if @song_count == 1
@user_horse.base_speed += 3
else
@user_horse.base_speed -= 1
end
end
end
# def get_corner_strategy
# end
# def process_postgame
# end
def retrieve_race_section
@race_sections.shift
end
def calculate_leader
leader_hash = {user_horse: @user_horse.progress, opponent_horse_1: @opponent_horse_1.progress, opponent_horse_2: @opponent_horse_2.progress}.max_by {|k,v| v}
leader = leader_hash.each do |key, value|
end
if leader[0] == :user_horse
@user_horse.name
elsif leader[0] == :opponent_horse_1
@opponent_horse_1.name
else
@opponent_horse_2.name
end
end
############ utilities
def clear_screen
system "clear"
end
def pause
gets.chomp
end
def measure_terminal_window
x = `tput cols`.to_i
end
end
class Track
attr_accessor :distance
def initialize
weather = ["70 degrees and sunny.", "Overcast and muddy. It's been running for days.", "Overcast and sprinkling.", "Hot. Very Hot."]
@distance = 0
@weather = weather[rand(0..3)]
end
end
class Horse
attr_accessor :progress, :base_speed, :stamina
attr_reader :name, :song
def initialize(opponent_data)
@name = opponent_data[:name]
@base_speed = opponent_data[:base_speed]
@stamina = opponent_data[:stamina]
@song = opponent_data[:song]
@progress = 0
end
def run
self.base_speed * 2 + rand(0..2)
end
end
class UserHorse
attr_accessor :progress, :base_speed, :stamina, :name
def initialize
#set song
@base_speed = 7
@stamina = 7
@progress = 0
@name = 'Playr 1'
end
def run
check_stamina
self.base_speed * 2 + rand(0..2)
end
def check_stamina
if self.stamina < 5
unless self.base_speed < 5
self.base_speed -= 1
end
end
end
end
class PrintTrack
def initialize
@counter = 1
@front_string = calculate_original_front_string
@section_width = calculate_section_width
@user_horse_begin = [ " .'' ",
"._.-.___.' (`\ ",
" //( ( `' ",
" '/ )\ ).__. ) ",
" ' <' `\ ._/'\ ",
" ` \ "
]
@opponent_horse_begin = [ " .'' ",
"._.-.___.' (`\ ",
" //( ( `' ",
" '/ )\ ).__. ) ",
" ' <' `\ ._/'\ ",
" ` \ "
]
@opponent_horse_finish = [ " .'' ",
"._.-.___.' (`\ ",
" //( ( `' ",
" '/ )\ ).__. )",
" ' <' `\ ._/'\ ",
" ` \ "
]
end
def process_print(counter, game)
@current_game = game
user_horse_string = "#{@current_game.user_horse.name} (Speed: #{@current_game.user_horse.base_speed})"
opponent_1_horse_string = "#{@current_game.opponent_horse_1.name} (Speed: #{@current_game.opponent_horse_1.base_speed})"
opponent_2_horse_string = "#{@current_game.opponent_horse_2.name} (Speed: #{@current_game.opponent_horse_2.base_speed})"
@user_horse_begin << user_horse_string
if counter == 13
case check_winner
when 0
print_user_horse_wins
@opponent_horse_begin << opponent_1_horse_string
print_opponent_horse(counter, 1)
@opponent_horse_begin.pop
@opponent_horse_begin << opponent_2_horse_string
print_opponent_horse(counter, 2)
@opponent_horse_begin.pop
when 1
print_user_horse(counter)
@opponent_horse_begin << opponent_1_horse_string
print_opponent_horse_wins
@opponent_horse_begin.pop
@opponent_horse_begin << opponent_2_horse_string
print_opponent_horse(counter, 2)
@opponent_horse_begin.pop
when 2
print_user_horse(counter)
@opponent_horse_begin << opponent_1_horse_string
print_opponent_horse(counter, 1)
@opponent_horse_begin.pop
@opponent_horse_begin << opponent_2_horse_string
print_opponent_horse_wins
@opponent_horse_begin.pop
end
else
print_user_horse(counter)
@opponent_horse_begin << opponent_1_horse_string
print_opponent_horse(counter, 1)
@opponent_horse_begin.pop
@opponent_horse_begin << opponent_2_horse_string
print_opponent_horse(counter, 2)
@opponent_horse_begin.pop
end
sleep 1
@user_horse_begin.pop
end
def print_user_horse(counter)
update_front_string
system 'clear'
print_lane_line
print_lane_line
if counter == 11
loop_counter = 0
@user_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_user_placement) + horse_string + " " + select_finish_section(loop_counter)
loop_counter += 1
end
elsif counter == 12
loop_counter = 0
@user_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_user_placement) + horse_string + " " + select_finish_section(loop_counter)
loop_counter += 1
end
elsif counter == 13
loop_counter = 0
@user_horse_begin.each do |horse_string|
puts @front_string + horse_string + select_finish_section(loop_counter)
loop_counter += 1
end
else
@user_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_user_placement) + horse_string
end
end
print_lane_line
print_lane_line
end
def print_opponent_horse(counter, horse_num)
if counter == 11
loop_counter = 0
@opponent_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_opponent_horse_placement(horse_num)) + horse_string + " " + select_finish_section(loop_counter)
loop_counter += 1
end
elsif counter == 12
loop_counter = 0
@opponent_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_opponent_horse_placement(horse_num)) + horse_string + " " + select_finish_section(loop_counter)
loop_counter += 1
end
elsif counter == 13
loop_counter = 0
@opponent_horse_begin.each do |horse_string|
puts @front_string + horse_string + select_finish_section(loop_counter)
loop_counter += 1
end
else
@opponent_horse_begin.each do |horse_string|
puts @front_string.slice(adjust_opponent_horse_placement(horse_num)) + horse_string
end
end
print_lane_line
print_lane_line
end
def print_user_horse_wins
system 'clear'
print_lane_line
print_lane_line
loop_counter = 0
@user_horse_begin.each do |horse_string|
puts @front_string + select_finish_section(loop_counter) + horse_string
loop_counter += 1
end
print_lane_line
print_lane_line
end
def print_opponent_horse_wins
loop_counter = 0
@opponent_horse_finish.each do |horse_string|
puts @front_string + select_finish_section(loop_counter) + horse_string
loop_counter += 1
end
print_lane_line
print_lane_line
end
def check_winner
horses = {:user_horse => @current_game.user_horse.progress, :opponent_horse_1 => @current_game.opponent_horse_1.progress, :opponent_horse_2 => @current_game.opponent_horse_2.progress}
sorted_horses = horses.sort_by { |name, progress| progress}
if sorted_horses[2][0] == :user_horse
0
elsif sorted_horses[2][0] == :opponent_horse_1
1
else
2
end
end
def adjust_user_placement
horses = {:user_horse => @current_game.user_horse.progress, :opponent_horse_1 => @current_game.opponent_horse_1.progress, :opponent_horse_2 => @current_game.opponent_horse_2.progress}
sorted_horses = horses.sort_by { |name, progress| progress}
if sorted_horses[0][0] == :user_horse
' ' * (@front_string.length - 10)
elsif sorted_horses[1][0] == :user_horse
' ' * (@front_string.length - 5)
else
@front_string
end
end
def adjust_opponent_horse_placement(horse)
horses = {:user_horse => @current_game.user_horse.progress, :opponent_horse_1 => @current_game.opponent_horse_1.progress, :opponent_horse_2 => @current_game.opponent_horse_2.progress}
sorted_horses = horses.sort_by { |name, progress| progress}
horse_symbol = "opponent_horse_#{horse}".to_sym
if sorted_horses[0][0] == horse_symbol
' ' * (@front_string.length - 9)
elsif sorted_horses[1][0] == horse_symbol
' ' * (@front_string.length - 4)
else
@front_string
end
end
def select_finish_section(counter)
finish_line = ["# F #", "# I #", "# N #", "# I #", "# S #", "# H #", ""]
finish_line[counter.to_i]
end
##### utilities ####
def get_screen_width
`tput cols`.to_i
end
def calculate_section_width
section_width = (get_screen_width - 35) / 13
section_width.to_i
end
def print_lane_line
system "printf \"%`tput cols`s\"|tr ' ' '#'"
end
def calculate_original_front_string
" " * calculate_section_width
end
def update_front_string
@front_string += calculate_original_front_string
end
end
class User
def initialize
@game_history = []
end
end
Game.new
#also need current speed; base speed doing too much work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment