module BattleshipsGame
Constants
- AI_OPPONENT
- PLUGIN
- STYLE_TITLE
- STYLE_WIN
Public Instance Methods
Source
# File lib/battleships_game.rb, line 207 def ai_game?(game) game["mode"] == "ai" || game["target"] == AI_OPPONENT end
Source
# File lib/battleships_game.rb, line 219 def display_name(game, key) key == AI_OPPONENT ? "AI" : key end
Source
# File lib/battleships_game.rb, line 80 def fire(game:, user:, coord:, rand: ->(max) { Random.rand(0...max) }) return { error: "No active game." } unless game && game["stage"] == "active" return { error: "You are not in this game." } unless player?(game, user) return { error: "Not your turn." } unless GameStore.same_nick?(user, game["turn"]) index = BattleshipBoard.coord_to_index(coord) return { error: "Invalid coordinate (A1-J10)." } unless index player = GameStore.norm_nick(user) opponent = opponent_for(game, player) shots = (game["shots"][player] || {}).dup coord_key = BattleshipBoard.index_to_coord(index) return { error: "Already fired at #{coord_key}." } if shots.key?(coord_key) fleets = game["fleets"].transform_values(&:dup) result = BattleshipBoard.fire(fleet: fleets[opponent], index: index) return result if result[:error] fleets[opponent] = result[:fleet] shots[coord_key] = result[:result] game = game.dup game["fleets"] = fleets game["shots"] = game["shots"].dup game["shots"][player] = shots lines = [format_header("Salvo")] lines << "#{player} fires at #{coord_key} โ #{result_label(result)}" if result[:sunk] lines << "You sunk their #{result[:ship_name]}!" end if BattleshipBoard.all_sunk?(fleets[opponent]) game["stage"] = "done" game["winner"] = player lines << "#{IrcFormat.decorate(player, STYLE_WIN)} wins โ all enemy ships sunk!" return { game: game, message: lines.join("\n") + "\n" + IrcFormat.report_footer("battleships"), done: true } end game["turn"] = opponent if ai_game?(game) && opponent == AI_OPPONENT ai_result = fire_ai_turn(game, rand: rand) if ai_result[:done] return { game: ai_result[:game], message: lines.join("\n") + "\n" + ai_result[:message], done: true } end game = ai_result[:game] lines << ai_result[:line] game["turn"] = player end lines << "Turn: #{display_name(game, game['turn'])}" { game: game, message: lines.join("\n") } end
Source
# File lib/battleships_game.rb, line 138 def fire_ai_turn(game, rand:) coord = BattleshipAi.pick_shot(game: game, rand: rand) index = BattleshipBoard.coord_to_index(coord) human = game["challenger"] shots = (game["shots"][AI_OPPONENT] || {}).dup fleets = game["fleets"].transform_values(&:dup) result = BattleshipBoard.fire(fleet: fleets[human], index: index) fleets[human] = result[:fleet] shots[coord] = result[:result] game = game.dup game["fleets"] = fleets game["shots"] = game["shots"].dup game["shots"][AI_OPPONENT] = shots line = "AI fires at #{coord} โ #{result_label(result)}" line += " โ your #{result[:ship_name]} sunk!" if result[:sunk] if BattleshipBoard.all_sunk?(fleets[human]) game["stage"] = "done" game["winner"] = AI_OPPONENT message = [ format_header("Defeat"), line, "AI wins โ your fleet is destroyed.", IrcFormat.report_footer("battleships") ].join("\n") return { game: game, message: message, done: true } end { game: game, line: line } end
Source
# File lib/battleships_game.rb, line 171 def format_board(game, user:) return format_header("No game") + "\nNo battleships game in progress." unless game player = GameStore.norm_nick(user) return format_header("Spectator") + "\nYou are not in this game." unless player?(game, player) opponent = opponent_for(game, player) own = BattleshipBoard.render_own(game["fleets"][player]) target = BattleshipBoard.render_target(game["shots"][player] || {}) [ format_header("#{player} โ fleet"), own, format_header("Target grid"), target, IrcFormat.report_footer("!battleships fire <coord>") ].join("\n") end
Source
# File lib/battleships_game.rb, line 232 def format_header(title) IrcFormat.report_header(tag: "SHIPS", title: title, style: STYLE_TITLE) end
Source
# File lib/battleships_game.rb, line 189 def format_status(game) return format_header("No game") + "\nNo battleships in progress." unless game challenger = game["challenger"] target = display_name(game, game["target"]) lines = [format_header("#{challenger} vs #{target}")] lines << "Stage: #{game['stage']}" lines << "Turn: #{display_name(game, game['turn'])}" if game["turn"] && game["stage"] == "active" lines << IrcFormat.report_footer(game["stage"]) lines.join("\n") end
Source
# File lib/battleships_game.rb, line 211 def opponent_for(game, player) if GameStore.same_nick?(player, game["challenger"]) game["target"] else game["challenger"] end end
Source
# File lib/battleships_game.rb, line 21 def parse_command(text) base = AsyncDuel.parse_base(text, usage: usage_message) return base unless base[:action] == :unknown parts = base[:tail] case parts[0].downcase when "ai" { action: :ai } when "fire" return { error: usage_message } if parts.length < 2 { action: :fire, coord: parts[1].upcase } when "board" { action: :board } else if parts[0].match?(/\A[A-J](10|[1-9])\z/i) { action: :fire, coord: parts[0].upcase } else { error: usage_message } end end end
Source
# File lib/battleships_game.rb, line 201 def player?(game, user) GameStore.same_nick?(user, game["challenger"]) || GameStore.same_nick?(user, game["target"]) || (ai_game?(game) && GameStore.same_nick?(user, game["challenger"])) end
Source
# File lib/battleships_game.rb, line 223 def result_label(result) case result[:result] when :miss then "miss" when :hit then "hit" when :sunk then "sunk" else result[:result].to_s end end
Source
# File lib/battleships_game.rb, line 44 def start_ai_game(user:, rand: ->(max) { Random.rand(0...max) }) challenger = GameStore.norm_nick(user) game = { "stage" => "active", "mode" => "ai", "challenger" => challenger, "target" => AI_OPPONENT, "turn" => challenger, "fleets" => {}, "shots" => {} } started = start_game(game, rand: rand) started[:message] = "#{format_header('vs AI')}\n#{started[:message]}\n#{challenger} fires first โ !battleships fire <coord>" started end
Source
# File lib/battleships_game.rb, line 60 def start_game(game, rand: ->(max) { Random.rand(0...max) }) game = game.dup game["stage"] = "active" game["mode"] ||= "duel" game["fleets"] = { game["challenger"] => BattleshipBoard.place_fleet_random(rand: rand), game["target"] => BattleshipBoard.place_fleet_random(rand: rand) } game["shots"] = { game["challenger"] => {}, game["target"] => {} } game["turn"] ||= game["challenger"] opponent = display_name(game, game["target"]) { game: game, message: "Fleets deployed.\n#{game['challenger']} vs #{opponent}\n!battleships board ยท !battleships fire A1" } end
Source
# File lib/battleships_game.rb, line 17 def usage_message "Usage: !battleships ai | challenge <nick> | accept | decline | fire <coord> | board | status" end