Evolve to mutlipod management.

This commit is contained in:
Glenn Y. Rolland 2016-08-07 01:00:26 +02:00
parent 2be6ac9930
commit 1089f6cd49
2 changed files with 234 additions and 197 deletions

View file

@ -11,7 +11,7 @@ let module Vector = struct
} }
let to_string dst : string = let to_string dst : string =
(Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y) (Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y)
let create x y = { x ; y } let create x y = { x ; y }
@ -20,7 +20,7 @@ let module Vector = struct
let diff dst src = let diff dst src =
{ x = (dst.x - src.x) ; { x = (dst.x - src.x) ;
y = (dst.y - src.y) y = (dst.y - src.y)
} }
let mult src a = let mult src a =
{ x = src.x * a ; { x = src.x * a ;
@ -38,7 +38,7 @@ let module Vector = struct
|> sqrt |> sqrt
|> int_of_float |> int_of_float
let is_touching dst src = let is_touching dst src =
(distance dst src) < (checkpoint_ray / 2) (distance dst src) < (checkpoint_ray / 2)
let is_near dst src = let is_near dst src =
@ -48,108 +48,107 @@ let module Vector = struct
((distance dst src) >= checkpoint_ray * 6) ((distance dst src) >= checkpoint_ray * 6)
end in end in
let module Pod = struct let module Pod = struct
type t = { type t = {
pos : Vector.t ; pos : Vector.t ;
dir : Vector.t ; dir : Vector.t ;
} }
end in end in
let module CheckpointList = struct let module CheckpointList = struct
type t = { type t = {
mem: Vector.t list ; mem: Vector.t list ;
cur: Vector.t option cur: Vector.t option
} }
let add ck_li elem = let add ck_li elem =
match ck_li.cur with match ck_li.cur with
| None -> | None ->
{ {
mem = [] ; mem = [] ;
cur = Some elem cur = Some elem
} }
| Some cur_elem -> | Some cur_elem ->
if (Vector.equal cur_elem elem) then if (Vector.equal cur_elem elem) then
ck_li ck_li
else else
{ {
mem = cur_elem :: ck_li.mem ; mem = cur_elem :: ck_li.mem ;
cur = Some elem cur = Some elem
} }
let create () = let create () =
{ mem = [] ; { mem = [] ;
cur = None cur = None
} }
let inc (ck_li:t) elem = let inc (ck_li:t) elem =
(ck_li.mem) (ck_li.mem)
|> List.map (fun cur -> (Vector.equal elem cur)) |> List.map (fun cur -> (Vector.equal elem cur))
|> List.fold_left (fun acc elem -> acc || elem) false |> List.fold_left (fun acc elem -> acc || elem) false
end in
end in let parse_line1 () =
let line = input_line stdin in
let parse_line1 () = let build_results_fn = (
let line = input_line stdin in fun x y checkpointx checkpointy checkpointdist checkpointangle ->
let build_results_fn = ( (Vector.create x y),
fun x y checkpointx checkpointy checkpointdist checkpointangle ->
(Vector.create x y),
(Vector.create checkpointx checkpointy), (Vector.create checkpointx checkpointy),
checkpointdist, checkpointdist,
checkpointangle checkpointangle
) in ) in
Scanf.sscanf line "%d %d %d %d %d %d" build_results_fn Scanf.sscanf line "%d %d %d %d %d %d" build_results_fn
in in
let parse_line2 () = let parse_line2 () =
let line = input_line stdin in let line = input_line stdin in
let build_results_fn = ( let build_results_fn = (
fun opponentx opponenty -> fun opponentx opponenty ->
(Vector.create opponentx opponenty) (Vector.create opponentx opponenty)
) in ) in
Scanf.sscanf line "%d %d" build_results_fn Scanf.sscanf line "%d %d" build_results_fn
in in
let map_center = Vector.create (16000 / 2) (9000 / 2) in let map_center = Vector.create (16000 / 2) (9000 / 2) in
let first_turn = ref true in let first_turn = ref true in
let old_pod = ref (Vector.create 0 0) in let old_pod = ref (Vector.create 0 0) in
let tick = ref 0 in let tick = ref 0 in
let checkpoint_list = ref (CheckpointList.create ()) in let checkpoint_list = ref (CheckpointList.create ()) in
(* game loop *) (* game loop *)
while true do while true do
(* nextcheckpointdist: distance to the next checkpoint *) (* nextcheckpointdist: distance to the next checkpoint *)
(* nextcheckpointangle: angle between your pod orientation and the direction of 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 pod, checkpoint, checkpoint_dist, checkpoint_angle = parse_line1 () in
let opponent = parse_line2 () in let opponent = parse_line2 () in
if !first_turn then begin if !first_turn then begin
old_pod := pod ; old_pod := pod ;
first_turn := false first_turn := false
end ; end ;
let movement = Vector.diff pod !old_pod in let movement = Vector.diff pod !old_pod in
if (CheckpointList.inc !checkpoint_list checkpoint) then begin if (CheckpointList.inc !checkpoint_list checkpoint) then begin
prerr_endline "List already includes this checkpoint" ; prerr_endline "List already includes this checkpoint" ;
end else begin end else begin
checkpoint_list := (CheckpointList.add !checkpoint_list checkpoint) ; checkpoint_list := (CheckpointList.add !checkpoint_list checkpoint) ;
fprintf stderr "New checkpoint : %s\n%!" (Vector.to_string checkpoint); fprintf stderr "New checkpoint : %s\n%!" (Vector.to_string checkpoint);
end ; end ;
(* output "x y thrust" : the target position + the power *) (* output "x y thrust" : the target position + the power *)
let is_aligned = checkpoint_angle > -2 && checkpoint_angle < 2 in let is_aligned = checkpoint_angle > -2 && checkpoint_angle < 2 in
let is_near_aligned = let is_near_aligned =
(checkpoint_angle > -15 && checkpoint_angle <= -2) || (checkpoint_angle > -15 && checkpoint_angle <= -2) ||
(checkpoint_angle >= 2 && checkpoint_angle < 15) (checkpoint_angle >= 2 && checkpoint_angle < 15)
in in
let is_wide_aligned = let is_wide_aligned =
(checkpoint_angle > -45 && checkpoint_angle <= -15) || (checkpoint_angle > -45 && checkpoint_angle <= -15) ||
(checkpoint_angle >= 15 && checkpoint_angle < 45) (checkpoint_angle >= 15 && checkpoint_angle < 45)
in in
let is_aside = let is_aside =
(checkpoint_angle > -85 && checkpoint_angle <= -45) || (checkpoint_angle > -85 && checkpoint_angle <= -45) ||
(checkpoint_angle >= 45 && checkpoint_angle < 85) (checkpoint_angle >= 45 && checkpoint_angle < 85)
in in
let is_behind = checkpoint_angle >= 85 || checkpoint_angle <= -85 in let is_behind = checkpoint_angle >= 85 || checkpoint_angle <= -85 in
@ -174,7 +173,7 @@ while true do
in in
let target = let target =
Vector.mult movement (-3) Vector.mult movement (-3)
|> Vector.add checkpoint |> Vector.add checkpoint
in in
@ -182,5 +181,5 @@ while true do
tick := !tick + 1 ; tick := !tick + 1 ;
old_pod := pod ; old_pod := pod ;
done; done;

View file

@ -7,31 +7,31 @@ let checkpoint_ray = 600 in
let module Vector = struct let module Vector = struct
type t = { type t = {
x : int; x : int;
y : int y : int
} }
let to_string dst : string = let to_string dst : string =
(Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y) (Printf.sprintf "{ x = %d ; y = %d }" dst.x dst.y)
let create x y = let create x y =
{ x ; y } { x ; y }
let equal dst src = let equal dst src =
(dst.x = src.x) && (dst.y = src.y) (dst.x = src.x) && (dst.y = src.y)
let diff dst src = let diff dst src =
{ x = (dst.x - src.x) ; { x = (dst.x - src.x) ;
y = (dst.y - src.y) y = (dst.y - src.y)
} }
let mult src a = let mult src a =
{ x = src.x * a ; { x = src.x * a ;
y = src.y * a y = src.y * a
} }
let add dst src = let add dst src =
{ x = (src.x + dst.x) ; { x = (src.x + dst.x) ;
y = (src.y + dst.y) y = (src.y + dst.y)
} }
let distance (dst:t) (src:t) = let distance (dst:t) (src:t) =
@ -40,7 +40,7 @@ let module Vector = struct
|> sqrt |> sqrt
|> int_of_float |> int_of_float
let is_touching dst src = let is_touching dst src =
(distance dst src) < (checkpoint_ray / 2) (distance dst src) < (checkpoint_ray / 2)
let is_near dst src = let is_near dst src =
@ -52,71 +52,154 @@ end in
let module Pod = struct let module Pod = struct
type t = { type t = {
mutable id : int ;
mutable pos : Vector.t ; mutable pos : Vector.t ;
mutable dir : Vector.t ; mutable dir : Vector.t ;
} mutable has_boost : bool ;
mutable checkpoint_pos : Vector.t ;
mutable checkpoint_dist : int ;
mutable checkpoint_angle : int ;
mutable output_str : string
}
let create () = let create () =
{ pos = Vector.create 0 0 ; {
dir = Vector.create 0 0 id = 0 ;
pos = Vector.create 0 0 ;
dir = Vector.create 0 0 ;
has_boost = true ;
checkpoint_pos = Vector.create 0 0 ;
checkpoint_dist = 0 ;
checkpoint_angle = 0 ;
output_str = ""
} }
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
end in end in
let module CheckpointList = struct let module CheckpointList = struct
type t = { type t = {
mem: Vector.t list ; mem: Vector.t list ;
cur: Vector.t option cur: Vector.t option
} }
let add ck_li elem = let add ck_li elem =
match ck_li.cur with match ck_li.cur with
| None -> | None ->
{ {
mem = [] ; mem = [] ;
cur = Some elem cur = Some elem
} }
| Some cur_elem -> | Some cur_elem ->
if (Vector.equal cur_elem elem) then if (Vector.equal cur_elem elem) then
ck_li ck_li
else else
{ {
mem = cur_elem :: ck_li.mem ; mem = cur_elem :: ck_li.mem ;
cur = Some elem cur = Some elem
}
let create () =
{ mem = [] ;
cur = None
} }
let inc (ck_li:t) elem = let create () =
(ck_li.mem) { mem = [] ;
|> List.map (fun cur -> (Vector.equal elem cur)) cur = None
|> List.fold_left (fun acc elem -> acc || elem) false }
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 end in
let parse_line1 () = let module Game = struct
type t = {
pods : Pod.t array ;
opponents : Pod.t array ;
ticks : int ;
}
end in
let module Strategy = struct
let apply game pod =
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 ;
end in
let parse_pod_line () =
let line = input_line stdin in let line = input_line stdin in
let build_results_fn = ( let build_results_fn = (
fun x y checkpointx checkpointy checkpointdist checkpointangle -> fun x y checkpointx checkpointy checkpointdist checkpointangle ->
(Vector.create x y), (Vector.create x y),
(Vector.create checkpointx checkpointy), (Vector.create checkpointx checkpointy),
checkpointdist, checkpointdist,
checkpointangle checkpointangle
) in ) in
Scanf.sscanf line "%d %d %d %d %d %d" build_results_fn Scanf.sscanf line "%d %d %d %d %d %d" build_results_fn
in 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 map_center = Vector.create (16000 / 2) (9000 / 2) in
let first_turn = ref true in let first_turn = ref true in
let old_pod = ref (Vector.create 0 0) in let old_pod = ref (Vector.create 0 0) in
@ -126,89 +209,44 @@ let checkpoint_list = ref (CheckpointList.create ()) in
(* laps : le nombre de tours à effectuer pour finir la course. *) (* laps : le nombre de tours à effectuer pour finir la course. *)
let parse_init () = let parse_init () =
let laps = let laps =
let line = input_line stdin in let line = input_line stdin in
Scanf.sscanf line "%d" (fun x -> x) Scanf.sscanf line "%d" (fun x -> x)
in in
let checkpoint_count = let checkpoint_count =
let line = input_line stdin in let line = input_line stdin in
Scanf.sscanf line "%d" (fun x -> x) Scanf.sscanf line "%d" (fun x -> x)
in in
let parse_checkpoint () = let parse_checkpoint () =
let line = input_line stdin in let line = input_line stdin in
Scanf.sscanf line "%d %d" (fun x y -> Scanf.sscanf line "%d %d" (fun x y ->
Vector.create x y Vector.create x y
) )
in in
for i = 1 to checkpoint_count do for i = 1 to checkpoint_count do
let checkpoint = parse_checkpoint () in let checkpoint = parse_checkpoint () in
checkpoint_list := CheckpointList.add !checkpoint_list checkpoint ; checkpoint_list := CheckpointList.add !checkpoint_list checkpoint ;
() ()
done done
in in
let pods = Array.create 2 (Pod.create ()) in let pods = Array.make 2 (Pod.create ()) in
let game = Game.create () in
(* game loop *) (* game loop *)
while true do while true do
(* read pod1 line & update game data *)
parse_pod_line () |> Pod.update game.pods.(0) ;
parse_pod_line () |> Pod.update game.pods.(1) ;
parse_pod_line () |> Pod.update game.opponents.(0) ;
parse_pod_line () |> Pod.update game.opponents.(1) ;
for i = 0 to 1 do
(* nextcheckpointdist: distance to the next checkpoint *) game.pods.(i)
(* nextcheckpointangle: angle between your pod orientation and the direction of the next checkpoint *) |> Pod.update pod1_data
let pod, checkpoint, checkpoint_dist, checkpoint_angle = parse_line1 () in |> Strategy.apply
let opponent = parse_line2 () in |> fun pod -> print_endline pod.output_str ;
done
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 ; tick := !tick + 1 ;
old_pod := pod ; old_pod := pod ;