challenge-codinggame/coders-strike-back/code6.ml

316 lines
7.2 KiB
OCaml
Raw Permalink Normal View History

2016-08-01 13:15:17 +00:00
let open Printf in
let debug = fprintf stderr in
let checkpoint_ray = 600 in
let module Vector = struct
type t = {
x : int;
2016-08-06 23:00:26 +00:00
y : int
2016-08-01 13:15:17 +00:00
}
let to_string dst : string =
2016-08-06 23:00:26 +00:00
(Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y)
2016-08-01 13:15:17 +00:00
let create x y =
{ x ; y }
let equal dst src =
2016-08-06 23:00:26 +00:00
(dst.x = src.x) && (dst.y = src.y)
2016-08-01 13:15:17 +00:00
let diff dst src =
{ x = (dst.x - src.x) ;
2016-08-06 23:00:26 +00:00
y = (dst.y - src.y)
2016-08-01 13:15:17 +00:00
}
let mult src a =
{ x = src.x * a ;
2016-08-06 23:00:26 +00:00
y = src.y * a
2016-08-01 13:15:17 +00:00
}
let add dst src =
{ x = (src.x + dst.x) ;
2016-08-06 23:00:26 +00:00
y = (src.y + dst.y)
2016-08-01 13:15:17 +00:00
}
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
2016-08-06 23:00:26 +00:00
let is_touching dst src =
2016-08-01 13:15:17 +00:00
(distance dst src) < (checkpoint_ray / 2)
2016-08-06 23:00:26 +00:00
2016-08-01 13:15:17 +00:00
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
2016-08-07 15:02:57 +00:00
type orientation_t =
| Behind
| Aside
| WideAligned
| NearAligned
| Aligned
type distance_t =
| Touching
| Near
| Anywhere
| Far
2016-08-01 13:15:17 +00:00
type t = {
2016-08-07 15:02:57 +00:00
mutable id : int ;
mutable pos : Vector.t ;
mutable old_pos : Vector.t ;
mutable dir : Vector.t ;
mutable has_boost : bool ;
mutable checkpoint_pos : Vector.t ;
mutable checkpoint_dist : int ;
2016-08-06 23:00:26 +00:00
mutable checkpoint_angle : int ;
2016-08-07 15:02:57 +00:00
mutable output_str : string
2016-08-06 23:00:26 +00:00
}
2016-08-01 13:15:17 +00:00
let create () =
2016-08-06 23:00:26 +00:00
{
id = 0 ;
pos = Vector.create 0 0 ;
2016-08-07 15:02:57 +00:00
old_pos = Vector.create 0 0 ;
2016-08-06 23:00:26 +00:00
dir = Vector.create 0 0 ;
has_boost = true ;
checkpoint_pos = Vector.create 0 0 ;
checkpoint_dist = 0 ;
checkpoint_angle = 0 ;
output_str = ""
2016-08-01 13:15:17 +00:00
}
2016-08-06 23:00:26 +00:00
let use_boost pod =
pod.has_boost <- false
let update pod (pos, checkpoint_pos, checkpoint_dist, checkpoint_angle) =
pod.pos <- pos ;
pod.checkpoint_pos <- checkpoint_pos ;
pod.checkpoint_dist <- checkpoint_dist ;
pod.checkpoint_angle <- checkpoint_angle ;
pod
2016-08-07 15:02:57 +00:00
let movement pod =
Vector.diff pod.pos pod.old_pos
let is_aligned pod =
pod.checkpoint_angle > -2 &&
pod.checkpoint_angle < 2
let is_near_aligned pod =
(pod.checkpoint_angle > -15 && pod.checkpoint_angle <= -2) ||
(pod.checkpoint_angle >= 2 && pod.checkpoint_angle < 15)
let is_wide_aligned pod =
(pod.checkpoint_angle > -45 && pod.checkpoint_angle <= -15) ||
(pod.checkpoint_angle >= 15 && pod.checkpoint_angle < 45)
let is_aside pod =
(pod.checkpoint_angle > -85 && pod.checkpoint_angle <= -45) ||
(pod.checkpoint_angle >= 45 && pod.checkpoint_angle < 85)
let is_behind pod =
pod.checkpoint_angle >= 85 || pod.checkpoint_angle <= -85
let is_checkpoint_far pod =
Vector.is_far pod.pos pod.checkpoint_pos
let target_orientation pod =
if is_aligned pod then Aligned
else if is_near_aligned pod then NearAligned
else if is_wide_aligned pod then WideAligned
else if is_aside pod then Aside
else Behind
let target_distance pod =
let dist = Vector.distance pod.pos pod.checkpoint_pos in
if dist <= (checkpoint_ray) then Touching
else if dist <= (checkpoint_ray * 3) then Near
else if dist > (checkpoint_ray * 2 * 3) then Far
else Anywhere
2016-08-06 23:00:26 +00:00
2016-08-01 13:15:17 +00:00
end in
let module CheckpointList = struct
2016-08-06 23:00:26 +00:00
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
2016-08-01 13:15:17 +00:00
}
2016-08-06 23:00:26 +00:00
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 module Game = struct
type t = {
2016-08-07 15:02:57 +00:00
pods : Pod.t array ;
opponents : Pod.t array ;
mutable turn : int ;
2016-08-06 23:00:26 +00:00
}
2016-08-07 15:02:57 +00:00
let create () =
{
pods = Array.make 2 (Pod.create ()) ;
opponents = Array.make 2 (Pod.create ()) ;
turn = 0
}
let is_first_turn game = game.turn < 2
let save_pods game =
(* old_pod := pod ; *)
ignore game
let tick game =
game.turn <- game.turn + 1
2016-08-06 23:00:26 +00:00
end in
let module Strategy = struct
2016-08-07 15:02:57 +00:00
let apply game pod =
if Game.is_first_turn game then begin
Game.save_pods game ;
2016-08-06 23:00:26 +00:00
end ;
2016-08-07 15:02:57 +00:00
let movement = Pod.movement in
2016-08-06 23:00:26 +00:00
2016-08-07 15:02:57 +00:00
(*
2016-08-06 23:00:26 +00:00
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 ;
2016-08-07 15:02:57 +00:00
*)
2016-08-06 23:00:26 +00:00
let use_boost =
2016-08-07 15:02:57 +00:00
(game.turn > 100) &&
(Pod.is_aligned pod) &&
(Pod.is_checkpoint_far pod)
2016-08-06 23:00:26 +00:00
in
let thrust =
(* droit devant *)
2016-08-07 15:02:57 +00:00
match (Pod.target_orientation pod, Pod.target_distance pod) with
(* | (Behind, TouchingOpponent) -> 20
| (Aside, TouchingOpponent) -> 20 *)
| (Behind, _) -> 6
| (Aside, Near) -> 10
| (WideAligned, Near) -> 20
| (NearAligned, Near) -> 40
| (_, _) -> 100
2016-08-06 23:00:26 +00:00
in
let power_str = match use_boost with
| false -> string_of_int thrust
| true -> "BOOST"
in
2016-08-07 15:02:57 +00:00
let target =
Vector.mult (Pod.movement pod) (-3)
|> Vector.add pod.checkpoint_pos
in
2016-08-06 23:00:26 +00:00
printf "%d %d %s\n%!" target.x target.y power_str ;
2016-08-01 13:15:17 +00:00
end in
2016-08-06 23:00:26 +00:00
let parse_pod_line () =
2016-08-01 13:15:17 +00:00
let line = input_line stdin in
let build_results_fn = (
fun x y checkpointx checkpointy checkpointdist checkpointangle ->
2016-08-06 23:00:26 +00:00
(Vector.create x y),
(Vector.create checkpointx checkpointy),
checkpointdist,
checkpointangle
2016-08-01 13:15:17 +00:00
) in
Scanf.sscanf line "%d %d %d %d %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 () =
2016-08-06 23:00:26 +00:00
let laps =
let line = input_line stdin in
Scanf.sscanf line "%d" (fun x -> x)
2016-08-01 13:15:17 +00:00
in
2016-08-06 23:00:26 +00:00
let checkpoint_count =
let line = input_line stdin in
Scanf.sscanf line "%d" (fun x -> x)
2016-08-01 13:15:17 +00:00
in
2016-08-06 23:00:26 +00:00
let parse_checkpoint () =
let line = input_line stdin in
Scanf.sscanf line "%d %d" (fun x y ->
Vector.create x y
)
2016-08-01 13:15:17 +00:00
in
2016-08-06 23:00:26 +00:00
for i = 1 to checkpoint_count do
let checkpoint = parse_checkpoint () in
checkpoint_list := CheckpointList.add !checkpoint_list checkpoint ;
()
done
in
2016-08-01 13:15:17 +00:00
2016-08-06 23:00:26 +00:00
let game = Game.create () in
2016-08-01 13:15:17 +00:00
2016-08-06 23:00:26 +00:00
(* game loop *)
while true do
(* read pod1 line & update game data *)
2016-08-07 15:02:57 +00:00
parse_pod_line () |> Pod.update game.pods.(0) |> ignore ;
parse_pod_line () |> Pod.update game.pods.(1) |> ignore ;
parse_pod_line () |> Pod.update game.opponents.(0) |> ignore ;
parse_pod_line () |> Pod.update game.opponents.(1) |> ignore ;
2016-08-01 13:15:17 +00:00
2016-08-06 23:00:26 +00:00
for i = 0 to 1 do
game.pods.(i)
2016-08-07 15:02:57 +00:00
(* |> Strategy.apply *)
|> (fun (pod : Pod.t) -> pod.output_str)
|> print_endline
;
done ;
2016-08-01 13:15:17 +00:00
2016-08-07 15:02:57 +00:00
Game.tick game ;
2016-08-01 13:15:17 +00:00
done;