Permalink
Browse files

The basic game.

  • Loading branch information...
1 parent 14aad24 commit 76cf6c942e9a55794c6d45e43cb69272b6020673 @JEG2 committed Feb 16, 2010
View
@@ -0,0 +1,2 @@
+log/*.log
+log/*.html
View
@@ -0,0 +1,17 @@
+require "rake/testtask"
+
+desc "Default task: run all tests"
+task :default => :test
+
+Rake::TestTask.new do |test|
+ test.libs << "test"
+ test.pattern = "test/*_test.rb"
+ test.warning = true
+ test.verbose = true
+end
+
+desc "Clear all log files"
+task :clear_logs do
+ system( "rm #{File.join(File.dirname(__FILE__), *%w[log *.{log,html}])} " +
+ "2> /dev/null" )
+end
View
@@ -0,0 +1,33 @@
+#!/usr/bin/env ruby -wKU
+
+$LOAD_PATH << File.join(File.dirname(__FILE__), *%w[.. lib])
+require "broadsides"
+
+log_name = "last_game"
+if arg = ARGV.find { |a| a =~ /\A--log(=.*)?/ }
+ if $1
+ log_name = $1[1..-1]
+ else
+ index = ARGV.index(arg) + 1
+ log_name = ARGV[index]
+ ARGV.delete_at(index)
+ end
+ ARGV.delete(arg)
+end
+
+begin
+ if log_name.empty?
+ game = Broadsides::Game.new(*ARGV)
+ else
+ log = { :log => open( File.join( File.dirname(__FILE__),
+ *%W[.. log #{log_name}.log] ), "w" ) }
+ game = Broadsides::Game.new(*(ARGV + [log]))
+ end
+ game.run
+ winner = game.finish
+ puts "#{winner} wins."
+rescue Exception => error
+ puts "USAGE: [--log NAME] #{$PROGRAM_NAME} PATH_TO_PLAYER_1 PATH_TO_PLAYER_2"
+ puts
+ puts "Error: #{error.message}"
+end
View
@@ -0,0 +1,192 @@
+#!/usr/bin/env ruby -wKU
+
+unless ARGV.first and File.exist? ARGV.first
+ abort "USAGE: #{$PROGRAM_NAME} PATH_TO_LOG"
+end
+
+require "erb"
+
+def move(from, plus, horizontal)
+ x = from[/[A-L]/][0]
+ y = from[/10|[1-9]/].to_i
+ horizontal ? "#{(x + plus).chr}#{y}" : "#{x.chr}#{y + plus}"
+end
+
+players = [ ]
+ships = { }
+shots = { }
+turn = 0
+winner = nil
+File.foreach(ARGV.first) do |line|
+ case line
+ when /\ASETUP players:(\w+),(\w+)\b/
+ players << $1 << $2
+ when /\ASHIPS (\w+)((?: [2-5]:[A-L](?:10|[1-9]):[HV]){5})\Z/
+ player = $1
+ ships[player] = Hash.new("water")
+ $2.strip.split.each do |ship|
+ length, start, horizontal = ship.split(":")
+ length = length.to_i
+ horizontal = horizontal == "H"
+ length.times do |n|
+ edge = case n
+ when 0
+ "#{horizontal ? 'left' : 'top'}_edge"
+ when length - 1
+ "#{horizontal ? 'right' : 'bottom'}_edge"
+ else
+ "#{horizontal ? 'horizontal' : 'vertical'}_middle"
+ end
+ ships[player][move(start, n, horizontal)] = "ship #{edge}"
+ end
+ end
+ when /\ASHOTS (\w+)((?: [A-L](?:10|[1-9]):(?:hit|miss))+)\Z/
+ player = $1
+ other = player == players.first ? players.last : players.first
+ shots[other] ||= Hash.new(%w[empty &nbsp;])
+ turn += 1
+ $2.strip.split.each do |shot|
+ where, result = shot.split(":")
+ shots[other][where] = [ "#{result} turn_#{turn}",
+ result == "hit" ? "X" : "O" ]
+ end
+ when /\AWINNER (\w+)\b/
+ winner = $1
+ end
+end
+
+ERB.new(DATA.read).run
+
+__END__
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
+ <title><%= game = File.basename(ARGV.first, ".log") %></title>
+ <style type="text/css" media="screen">
+ body {
+ margin: 0px;
+ text-align: center;
+ }
+ #page {
+ width: 800px;
+ margin: 10px auto;
+ }
+
+ table {
+ border-spacing: 0px;
+ border: 1px solid blue;
+ }
+ td {
+ width: 30px;
+ height: 30px;
+ margin: 0px;
+ padding: 0px;
+ }
+
+ div.left {
+ float: left;
+ }
+ div.right {
+ float: right;
+ }
+
+ td.water {
+ border: 1px solid blue;
+ background-color: #66CCFF;
+ }
+ td.ship {
+ background-color: #999999;
+ }
+ td.left_edge {
+ border: 1px solid #E6E6E6;
+ border-right: 1px solid #999999;
+ }
+ td.right_edge {
+ border: 1px solid #E6E6E6;
+ border-left: 1px solid #999999;
+ }
+ td.top_edge {
+ border: 1px solid #E6E6E6;
+ border-bottom: 1px solid #999999;
+ }
+ td.bottom_edge {
+ border: 1px solid #E6E6E6;
+ border-top: 1px solid #999999;
+ }
+ td.horizontal_middle {
+ border: 1px solid #E6E6E6;
+ border-left: 1px solid #999999;
+ border-right: 1px solid #999999;
+ }
+ td.vertical_middle {
+ border: 1px solid #E6E6E6;
+ border-top: 1px solid #999999;
+ border-bottom: 1px solid #999999;
+ }
+
+ span {
+ display: none;
+ }
+ .hit {
+ color: #DD0000;
+ }
+ .miss {
+ color: white;
+ }
+
+ .player {
+ font-weight: bold;
+ }
+
+ .controls span {
+ font-weight: bold;
+ }
+ </style>
+ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
+ </head>
+ <body>
+ <div id="page">
+ <h1><%= game %></h1>
+ <% players.each_with_index do |player, i| %>
+ <div class="<%= i.zero? ? "left" : "right" %>">
+ <table>
+ <% (1..10).each do |y| %>
+ <tr>
+ <% ("A".."L").each do |x| %>
+ <% xy = "#{x}#{y}" %>
+ <td class="<%= ships[player][xy] %>">
+ <span class="<%= shots[player][xy][0] %>">
+ <%= shots[player][xy][1] %>
+ </span>
+ </td>
+ <% end %>
+ </tr>
+ <% end %>
+ </table>
+ <p class="player"><%= player %></p>
+ </div>
+ <% end %>
+ <div class="controls">
+ <% 1.upto(turn) do |i| %>
+ <a href="#" class="link_<%= i %>"
+ style="<%= i == 1 ? "" : "display: none;" %>"
+ data-turn="<%= i %>">Next</a>
+ <% end %>
+ <span class="link_<%= turn + 1 %>">Winner: <%= winner %></span>
+ <script type="text/javascript" charset="utf-8">
+ $(document).ready(function() {
+ $('a').click(function(event) {
+ var link = $(this);
+ var turn = link.attr('data-turn');
+ $('.turn_' + turn).show();
+ link.hide();
+ $('.link_' + (parseInt(turn) + 1)).show();
+ });
+ });
+ </script>
+ </div>
+ </div>
+ </body>
+</html>
View
@@ -0,0 +1,40 @@
+#!/usr/bin/env ruby -wKU
+
+def name(player)
+ File.basename(player, '.rb')
+end
+
+log = ARGV.delete("--log") || "--log="
+players = Dir.glob(File.join(File.dirname(__FILE__), *%w[.. players *.rb]))
+score = Hash.new(0)
+
+players.each_with_index do |player1, i|
+ players[(i + 1)..-1].each do |player2|
+ next if player1 == player2
+ order = [player1, player2]
+ 10.times do |n|
+ game = "#{order.map { |player| name(player) }.join('_vs_')}_#{n}"
+ command = [File.join(File.dirname(__FILE__), "broadsides")]
+ command << log
+ command << game unless log.include? "="
+ command.push(*order)
+ $stdout.print "Running #{game}... "
+ $stdout.flush
+ result = `#{command.join(" ")}`
+ puts result
+ if result =~ /\A#{Regexp.escape(name(order.first))}\b/
+ score[order.first] += 1
+ else
+ score[order.last] += 1
+ end
+ order.unshift(order.pop)
+ end
+ end
+end
+
+puts
+puts "Final Scores"
+puts "============"
+players.sort_by { |player| -score[player] }.each do |player|
+ puts "#{name(player)}: #{score[player]}"
+end
View
@@ -0,0 +1,2 @@
+require "broadsides/player"
+require "broadsides/game"
Oops, something went wrong.

0 comments on commit 76cf6c9

Please sign in to comment.