5 # Play one move of a Cartagena game
13 require 'libcartagena'
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 'First Possible' => '/var/www/scripts.njae.me.uk/cartagena/robots/1',
38 'Random' => '/var/www/scripts.njae.me.uk/cartagena/robots/2'
42 '1' => '/var/www/scripts.njae.me.uk/cartagena/robots/1',
43 '2' => '/var/www/scripts.njae.me.uk/cartagena/robots/2'
47 # How long the robot has to respond
51 def generate_output(cgi
, returned_move
, annotation
)
52 if returned_move
.empty
?
55 return_part
= cgi
.p
{ "Result is: " } + "\n" + cgi
.h1
{ returned_move
} + "\n"
61 annotation_part
= cgi
.p
{ annotation
}
65 cgi
.head
{ "\n" + cgi
.title
{"Move result"} } + "\n" +
66 cgi
.body
{ return_part
+ annotation_part
}
73 cgi
= CGI
.new("html4")
75 chosen_robot
= cgi
['robot']
76 if $ROBOT_NAME_TABLE.has_key
? chosen_robot
77 chosen_robot_dir
= $ROBOT_NAME_TABLE[chosen_robot
]
78 chosen_robot_dir
.untaint
80 raise InvalidRobotError
, "#{chosen_robot} is not a valid robot code"
84 game
, moves
= Game
.read_game(cgi
['history'].downcase
.split("\n"))
85 rescue InvalidMoveError
=> error
86 raise(InvalidMoveInHistoryError
, error
.message
)
87 rescue GameWonNotice
=> error
88 raise(GameWonInHistoryError
, error
.message
)
91 current_directory
= Dir
.pwd
92 current_directory
.untaint
93 Dir
.chdir chosen_robot_dir
97 robot_input
= game
.players
.length
.to_s
+ "\n"
98 robot_input
+= game
.board
.positions
.collect
{|p
| p
.symbol
.to_s
}.join("\n") + "\n"
99 robot_input
+= (moves
.collect
{|m
| m
.format(game
.board
, true)}).join("\n") + "\n" if not moves
.empty
?
100 robot_input
+= (game
.current_player
+ 1).to_s
+ "\n"
101 robot_input
+= game
.players_cards
[game
.current_player
].collect
{|c
| c
.to_s
}.join("\n") + "\n" if not game
.players_cards
[game
.current_player
].empty
?
103 # cgi.out { generate_output(cgi, "", "passing robot #{game.players.length.to_s + "#" + (moves.collect {|m| m.to_s}).join('!\n!') + "#" + next_roll.to_s}!") }
104 # cgi.out { generate_output(cgi, "", "passing robot #{robot_input}!") }
107 Timeout
.timeout($ROBOT_TIMEOUT + 1) do
108 Open3
.popen3('./runme') do |robot_in
, robot_out
, robot_err
|
109 robot_in
<< robot_input
111 returned_move
= robot_out
.gets
112 returned_error
= robot_err
.gets
116 Dir
.chdir current_directory
118 # cgi.out { generate_output(cgi, "", "Returned move #{returned_move}; robot error was #{returned_error}!") }
120 raise(InvalidMoveError
, "Robot returned error '#{returned_error}'") if returned_error
!= nil
121 raise(InvalidMoveError
, "Null move") if returned_move
.nil? or returned_move
.empty
?
122 next_move
= returned_move
.chomp
.to_move(game
, true)
123 game
.apply_move
! next_move
125 # cgi.out { generate_output(cgi, "", "Applied move #{returned_move}!") }
126 cgi
.out
{ generate_output(cgi
, returned_move
, "") }
128 rescue InvalidMoveInHistoryError
=> error
129 cgi
.out
{ generate_output(cgi
, "", "Invalid move in history: #{error}") }
130 # puts "Invalid move in history: #{error}"
131 rescue GameWonInHistoryError
=> error
132 cgi
.out
{ generate_output(cgi
, "", "Game already won in historic moves: #{error}") }
133 # puts "Game already won in historic moves: #{error}"
135 rescue InvalidMoveError
=> error
136 cgi
.out
{ generate_output(cgi
, "", "Robot returned invalid move: #{error}") }
137 # puts "Robot returned invalid move: #{error}"
138 rescue GameWonNotice
=> error
139 cgi
.out
{ generate_output(cgi
, returned_move
, "Game won: #{error}") }
140 # puts "Robot returned #{returned_move}"
141 # puts "Game won: #{error}"
143 rescue InvalidRobotError
=> error
144 cgi
.out
{ generate_output(cgi
, "", "Invalid robot selection: #{error}") }
145 # puts "Invalid robot selection: #{error}"
146 rescue Timeout
::Error => error
147 cgi
.out
{ generate_output(cgi
, "", "Robot timed out") }
148 # puts "Robot timeout: #{error}"