Last active
August 29, 2015 13:58
-
-
Save judesamp/10014979 to your computer and use it in GitHub Desktop.
A horse racing game for the terminal
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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