diff --git a/coders-strike-back/code6.ml b/coders-strike-back/code6.ml new file mode 100644 index 0000000..6313b6c --- /dev/null +++ b/coders-strike-back/code6.ml @@ -0,0 +1,217 @@ + +let open Printf in +let debug = fprintf stderr in + +let checkpoint_ray = 600 in + +let module Vector = struct + type t = { + x : int; + y : int + } + + let to_string dst : string = + (Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y) + + let create x y = + { x ; y } + + let equal dst src = + (dst.x = src.x) && (dst.y = src.y) + + let diff dst src = + { x = (dst.x - src.x) ; + y = (dst.y - src.y) + } + + let mult src a = + { x = src.x * a ; + y = src.y * a + } + + let add dst src = + { x = (src.x + dst.x) ; + y = (src.y + dst.y) + } + + let distance (dst:t) (src:t) = + (src.x - dst.x) * (src.x - dst.x) + (src.y - dst.y) * (src.y - dst.y) + |> float_of_int + |> sqrt + |> int_of_float + + let is_touching dst src = + (distance dst src) < (checkpoint_ray / 2) + + let is_near dst src = + (distance dst src) < (checkpoint_ray * 2) + + let is_far dst src = + ((distance dst src) >= checkpoint_ray * 6) +end in + +let module Pod = struct + type t = { + mutable pos : Vector.t ; + mutable dir : Vector.t ; + } + + let create () = + { pos = Vector.create 0 0 ; + dir = Vector.create 0 0 + } +end in + +let module CheckpointList = struct + type t = { + mem: Vector.t list ; + cur: Vector.t option + } + + let add ck_li elem = + match ck_li.cur with + | None -> + { + mem = [] ; + cur = Some elem + } + | Some cur_elem -> + if (Vector.equal cur_elem elem) then + ck_li + else + { + mem = cur_elem :: ck_li.mem ; + cur = Some elem + } + + let create () = + { mem = [] ; + cur = None + } + + let inc (ck_li:t) elem = + (ck_li.mem) + |> List.map (fun cur -> (Vector.equal elem cur)) + |> List.fold_left (fun acc elem -> acc || elem) false + +end in + +let parse_line1 () = + let line = input_line stdin in + let build_results_fn = ( + fun x y checkpointx checkpointy checkpointdist checkpointangle -> + (Vector.create x y), + (Vector.create checkpointx checkpointy), + checkpointdist, + checkpointangle + ) in + Scanf.sscanf line "%d %d %d %d %d %d" build_results_fn +in + +let parse_line2 () = + let line = input_line stdin in + let build_results_fn = ( + fun opponentx opponenty -> + (Vector.create opponentx opponenty) + ) in + Scanf.sscanf line "%d %d" build_results_fn +in + +let map_center = Vector.create (16000 / 2) (9000 / 2) in +let first_turn = ref true in +let old_pod = ref (Vector.create 0 0) in + +let tick = ref 0 in +let checkpoint_list = ref (CheckpointList.create ()) in + +(* laps : le nombre de tours à effectuer pour finir la course. *) +let parse_init () = + let laps = + let line = input_line stdin in + Scanf.sscanf line "%d" (fun x -> x) + in + let checkpoint_count = + let line = input_line stdin in + Scanf.sscanf line "%d" (fun x -> x) + in + let parse_checkpoint () = + let line = input_line stdin in + Scanf.sscanf line "%d %d" (fun x y -> + Vector.create x y + ) + in + for i = 1 to checkpoint_count do + let checkpoint = parse_checkpoint () in + checkpoint_list := CheckpointList.add !checkpoint_list checkpoint ; + () + done +in + +let pods = Array.create 2 (Pod.create ()) in + +(* game loop *) +while true do + + + (* nextcheckpointdist: distance to the next checkpoint *) + (* nextcheckpointangle: angle between your pod orientation and the direction of the next checkpoint *) + let pod, checkpoint, checkpoint_dist, checkpoint_angle = parse_line1 () in + let opponent = parse_line2 () in + + if !first_turn then begin + old_pod := pod ; + first_turn := false + end ; + let movement = Vector.diff pod !old_pod in + + if (CheckpointList.inc !checkpoint_list checkpoint) then begin + prerr_endline "List already includes this checkpoint" ; + end else begin + checkpoint_list := (CheckpointList.add !checkpoint_list checkpoint) ; + fprintf stderr "New checkpoint : %s\n%!" (Vector.to_string checkpoint); + end ; + + (* output "x y thrust" : the target position + the power *) + let is_aligned = checkpoint_angle > -2 && checkpoint_angle < 2 in + let is_near_aligned = + (checkpoint_angle > -15 && checkpoint_angle <= -2) || + (checkpoint_angle >= 2 && checkpoint_angle < 15) + in + let is_wide_aligned = + (checkpoint_angle > -45 && checkpoint_angle <= -15) || + (checkpoint_angle >= 15 && checkpoint_angle < 45) + in + let is_aside = + (checkpoint_angle > -85 && checkpoint_angle <= -45) || + (checkpoint_angle >= 45 && checkpoint_angle < 85) + in + let is_behind = checkpoint_angle >= 85 || checkpoint_angle <= -85 in + let use_boost = (!tick > 100) && is_aligned && (Vector.is_far pod checkpoint) in + + debug "angle = %d\n%!" checkpoint_angle ; + + let thrust = + (* droit devant *) + if is_behind && (Vector.is_touching pod opponent) then 20 + else if is_aside && (Vector.is_touching pod opponent) then 20 + else if is_behind then 6 + else if is_aside && (Vector.is_near checkpoint pod) then 10 + else if is_wide_aligned && (Vector.is_near checkpoint pod) then 20 + else if is_near_aligned && (Vector.is_near checkpoint pod) then 40 + else 100 + in + + let power_str = match use_boost with + | false -> string_of_int thrust + | true -> "BOOST" + in + + let target = Vector.add checkpoint (Vector.mult movement (-3)) in + + printf "%d %d %s\n%!" target.x target.y power_str ; + + tick := !tick + 1 ; + old_pod := pod ; +done; + +