5 # Play one move of a Trap the Cap game
8 # ttc [ -b | --board-size SIZE ] [ -i | --input FILE ] [ -r | --robot ROBOT ] [ -h | --help ]
18 # Prevent dangerous operations
21 class InvalidRobotError
< StandardError
24 class NoInputFileError
< StandardError
27 class InvalidMoveInHistoryError
< StandardError
30 class GameWonInHistoryError
< StandardError
34 # A table of the known game-playing robots
37 'Always clockwise simple' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/1',
38 'Clockwise cloud' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/2',
39 'GA generation 1006' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/3'
43 '1' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/1',
44 '2' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/2',
45 '3' => '/var/www/scripts.njae.me.uk/trap-the-cap/robots/3'
49 # How long the robot has to respond
53 def generate_output(cgi
, returned_move
, annotation
)
54 if returned_move
.empty
?
57 return_part
= cgi
.p
{ "Result is: " } + "\n" + cgi
.h1
{ returned_move
} + "\n"
63 annotation_part
= cgi
.p
{ annotation
}
67 cgi
.head
{ "\n" + cgi
.title
{"Move result"} } + "\n" +
68 cgi
.body
{ return_part
+ annotation_part
}
75 cgi
= CGI
.new("html4")
77 chosen_robot
= cgi
['robot']
78 if $ROBOT_NAME_TABLE.has_key
? chosen_robot
79 chosen_robot_dir
= $ROBOT_NAME_TABLE[chosen_robot
]
80 chosen_robot_dir
.untaint
82 raise InvalidRobotError
, "#{chosen_robot} is not a valid robot code"
86 game
, moves
, next_roll
= Game
.read_game(cgi
['moves'].downcase
.split("\n"))
87 game
.apply_moves
! moves
88 rescue InvalidMoveError
=> error
89 raise(InvalidMoveInHistoryError
, error
.message
)
90 rescue GameWonNotice
=> error
91 raise(GameWonInHistoryError
, error
.message
)
94 current_directory
= Dir
.pwd
95 current_directory
.untaint
96 Dir
.chdir chosen_robot_dir
100 robot_input
= game
.players
.length
.to_s
+ "\n"
101 robot_input
+= (moves
.collect
{|m
| m
.to_s
}).join("\n") + "\n" if not moves
.empty
?
102 robot_input
+= next_roll
.to_s
104 # cgi.out { generate_output(cgi, "", "passing robot #{game.players.length.to_s + "#" + (moves.collect {|m| m.to_s}).join('!\n!') + "#" + next_roll.to_s}!") }
105 # cgi.out { generate_output(cgi, "", "passing robot #{robot_input}!") }
108 Timeout
.timeout($ROBOT_TIMEOUT + 1) do
109 Open3
.popen3('./runme') do |robot_in
, robot_out
, robot_err
|
110 robot_in
<< robot_input
112 returned_move
= robot_out
.gets
113 returned_error
= robot_err
.gets
117 Dir
.chdir current_directory
119 # cgi.out { generate_output(cgi, "", "Returned move #{returned_move}; robot error was #{returned_error}!") }
121 raise(InvalidMoveError
, "Robot returned error '#{returned_error}'") if returned_error
!= nil
122 raise(InvalidMoveError
, "Null move") if returned_move
.nil? or returned_move
.empty
?
123 next_move
= returned_move
.chomp
.to_move(game
)
124 game
.apply_move
! next_move
126 # cgi.out { generate_output(cgi, "", "Applied move #{returned_move}!") }
127 cgi
.out
{ generate_output(cgi
, returned_move
, "") }
129 rescue InvalidMoveInHistoryError
=> error
130 cgi
.out
{ generate_output(cgi
, "", "Invalid move in history: #{error}") }
131 # puts "Invalid move in history: #{error}"
132 rescue GameWonInHistoryError
=> error
133 cgi
.out
{ generate_output(cgi
, "", "Game already won in historic moves: #{error}") }
134 # puts "Game already won in historic moves: #{error}"
136 rescue InvalidMoveError
=> error
137 cgi
.out
{ generate_output(cgi
, "", "Robot returned invalid move: #{error}") }
138 # puts "Robot returned invalid move: #{error}"
139 rescue GameWonNotice
=> error
140 cgi
.out
{ generate_output(cgi
, returned_move
, "Game won: #{error}") }
141 # puts "Robot returned #{returned_move}"
142 # puts "Game won: #{error}"
144 rescue InvalidRobotError
=> error
145 cgi
.out
{ generate_output(cgi
, "", "Invalid robot selection: #{error}") }
146 # puts "Invalid robot selection: #{error}"
147 rescue Timeout
::Error => error
148 cgi
.out
{ generate_output(cgi
, "", "Robot timed out") }
149 # puts "Robot timeout: #{error}"