open Unix open Board open Types let space_regexp = Str.regexp " " let in_channel = ref (Obj.magic 0) let out_channel = ref (Obj.magic 0) let is_open = ref false let send s = output_string !out_channel s; flush !out_channel; print_string s; Pervasives.flush Pervasives.stdout let read_line () = try input_line !in_channel with End_of_file -> print_endline "server has closed connection."; if !Sys.interactive then raise End_of_file else exit 0 let split s = Str.split space_regexp s let read_board () = let l = read_line () in let x, y = match split l with [x;y] -> int_of_string x, int_of_string y | _ -> assert(1 = 2); (1000, 1000) in board_width := x; board_height := y; board := Array.create (y+2) (Array.create (x+2) Wall); for i = 1 to y do let bl = Array.create (x+2) Wall in let l = read_line () in for j = 1 to x do let e = match l.[j-1] with '.' -> Plain | '#' -> Wall | '~' -> Water | '@' -> (homes := LocSet.add (j, i) !homes; Home(0)) | _ -> failwith "unknown char in map" in bl.(j) <- e; done; !board.(i) <- bl done; Map_analyze.calculate_map_weight () let read_player_configulation () = let l = read_line () in match split l with [id; max_w; m] -> my_id := int_of_string id; max_weight := int_of_string max_w; money := int_of_string m | _ -> assert(1 = 2) let read_moves () = let n = ref IntMap.empty in let desc = ref (split (read_line ())) in let cur_id = ref (-1) in let cur_robot = ref (Obj.magic 0) in try while(true) do match !desc with [] -> raise Exit | hd::tl -> desc := tl; match hd.[0] with '#' -> begin let id = int_of_string (Str.string_after hd 1) in cur_id := id; cur_robot := ( try IntMap.find id !robots with Not_found -> { robot_loc = 0, 0; own = IntSet.empty } ); n := IntMap.add id (!cur_robot) !n end | 'N' -> let x, y = !cur_robot.robot_loc in !cur_robot.robot_loc <- x, y + 1 | 'E' -> let x, y = !cur_robot.robot_loc in !cur_robot.robot_loc <- x + 1, y | 'W' -> let x, y = !cur_robot.robot_loc in !cur_robot.robot_loc <- x - 1, y | 'S' -> let x, y = !cur_robot.robot_loc in !cur_robot.robot_loc <- x, y - 1 | 'P' -> begin dirty := true; match !desc with id :: rest -> desc := rest; let id = int_of_string id in !cur_robot.own <- IntSet.add id (!cur_robot.own); (* update packs *) let pack_info, _ = try IntMap.find id !packs with Not_found -> (* someone picked up a package which I was not aware of *) (* update Home *) let loc_x, loc_y = !cur_robot.robot_loc in (match !board.(loc_y).(loc_x) with Home(p) -> !board.(loc_y).(loc_x) <- Home(p + 1) | _ -> assert(1 = 2)); (None, Yes(!cur_robot.robot_loc)) in packs := IntMap.add id (pack_info, No) !packs; | _ -> assert(1 = 2) end | 'D' -> begin dirty := true; match !desc with id :: rest -> desc := rest; let id = int_of_string id in !cur_robot.own <- IntSet.remove id (!cur_robot.own); (* update packs *) let pack_info, _ = IntMap.find id !packs in packs := IntMap.add id (pack_info, let loc = !cur_robot.robot_loc in match pack_info with Some(pack_info) -> if loc = pack_info.dest then No else Yes(loc) | None -> Maybe(loc)) !packs | _ -> assert(1 = 2) end | 'X' -> begin match !desc with x :: y_str :: y :: rest -> desc := rest; !cur_robot.robot_loc <- int_of_string x, int_of_string y | _ -> assert(1 = 2) end | _ -> assert(1 = 2) done with Exit -> robots := !n let read_packs () = let desc = ref (split (read_line ())) in packs_here := IntSet.empty; (try while true do match !desc with [] -> raise Exit | id :: x :: y :: w :: tl -> desc := tl; let id = int_of_string id in let x = int_of_string x in let y = int_of_string y in let w = int_of_string w in packs_here := IntSet.add id !packs_here; packs := IntMap.add id (Some { weight = w; dest = (x, y)}, Yes(my_loc ())) !packs | _ -> assert(1 = 2) done with Exit -> ()); (* remove Home if I myself visit there *) homes := LocSet.remove (my_loc ()) !homes; (* (match !board.(my_y).(my_x) with Home(_) -> !board.(my_y).(my_x) <- Plain | _ -> ()); *) (* remove packages that turned out to have disappeared *) packs := IntMap.map (function (info, Maybe(loc)) when loc = my_loc () -> (info, No) | p -> p) !packs let send_cmd bid action = let print_direction = function N -> "N" | E -> "E" | S -> "S" | W -> "W" in let rec print_int_list = function [] -> "" | [n] -> string_of_int n | n::l -> (string_of_int n)^" "^(print_int_list l) in let print_action = function Move m -> "Move "^(print_direction m) | Pick l -> "Pick "^(print_int_list l) | Drop l -> "Drop "^(print_int_list l) in let cmd = (string_of_int bid)^" "^(print_action action)^"\n" in send cmd; money := !money - abs bid; read_moves (); read_packs (); (* Printer.print_robots !robots; Printer.print_homes (); Pervasives.flush Pervasives.stdout;*) () let init argv = let argstart = if !Sys.interactive then 0 else 1 in if Array.length argv < 2 + argstart then begin prerr_endline "usage: runme host port."; exit 1 end; let hostname = argv.(argstart) in let port = int_of_string (argv.(argstart + 1)) in let h = try gethostbyname hostname with Not_found -> prerr_endline "host not found. check hostname or use IP address."; exit 1 in let addr = h.h_addr_list.(0) in let i, o = open_connection (ADDR_INET(addr, port)) in in_channel := i; out_channel := o; is_open := true; send "Player\n"; read_board (); read_player_configulation (); read_moves (); read_packs () let close () = close_out !out_channel; close_in !in_channel; is_open := false