Skip to content

Commit 31d817f

Browse files
committed
Merge branch 'master' of github.com:imos/icfpc2020
2 parents fb35b65 + 5ee84d6 commit 31d817f

File tree

1 file changed

+313
-0
lines changed

1 file changed

+313
-0
lines changed

src/bin/app_totsugeki.rs

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
use app::client::*;
2+
3+
////////////////////////////////////////////////////////////////////////////////////////////////////
4+
5+
const SIZE_OUTER: i32 = 128;
6+
const SIZE_INNER: i32 = 16;
7+
const MAX_V: i32 = 16;
8+
const STEP_LIMIT: i32 = 5;
9+
10+
fn clip_int(x: i32, limit: i32) -> i32 {
11+
x.signum() * x.abs().min(limit)
12+
}
13+
14+
fn clip_pos(x: i32) -> i32 {
15+
x.signum() * x.abs().min(SIZE_OUTER - 1)
16+
}
17+
18+
////////////////////////////////////////////////////////////////////////////////////////////////////
19+
20+
#[derive(PartialEq, Copy, Clone, Debug)]
21+
struct PosVel {
22+
x: i32,
23+
y: i32,
24+
vx: i32,
25+
vy: i32,
26+
}
27+
28+
impl PosVel {
29+
pub fn new(x: i32, y: i32, vx: i32, vy: i32) -> Self {
30+
Self {
31+
x,
32+
y,
33+
vx,
34+
vy
35+
}
36+
}
37+
38+
pub fn new_empty() -> Self {
39+
Self {
40+
x: i32::MIN,
41+
y: i32::MIN,
42+
vx: i32::MIN,
43+
vy: i32::MIN,
44+
}
45+
}
46+
47+
pub fn is_empty(&self) -> bool {
48+
self.x == i32::MIN && self.y == i32::MIN && self.vx == i32::MIN && self.vy == i32::MIN
49+
}
50+
51+
pub fn get_gravity(&self) -> (i32, i32) {
52+
let apply_x = self.x.abs() >= self.y.abs();
53+
let apply_y = self.x.abs() <= self.y.abs();
54+
55+
let gx = {
56+
if apply_x {
57+
-self.x.signum()
58+
} else {
59+
0
60+
}
61+
};
62+
let gy = {
63+
if apply_y {
64+
-self.y.signum()
65+
} else {
66+
0
67+
}
68+
};
69+
70+
(gx, gy)
71+
}
72+
73+
pub fn apply_gravity(&self) -> Self {
74+
let (gx, gy) = self.get_gravity();
75+
Self {
76+
x: self.x,
77+
y: self.y,
78+
vx: self.vx + gx,
79+
vy: self.vy + gy,
80+
}
81+
}
82+
83+
pub fn accelerate_and_move(&self, dvx: i32, dvy: i32) -> Self {
84+
let vx = self.vx + dvx;
85+
let vy = self.vy + dvy;
86+
Self {
87+
x: self.x + vx,
88+
y: self.y + vy,
89+
vx,
90+
vy,
91+
}
92+
}
93+
94+
pub fn is_in_valid_area(&self) -> bool {
95+
if SIZE_OUTER <= self.x.abs() || SIZE_OUTER <= self.y.abs() {
96+
return false;
97+
}
98+
if self.x.abs() <= SIZE_INNER && self.y.abs() <= SIZE_INNER {
99+
return false;
100+
}
101+
if MAX_V <= self.vx.abs() || MAX_V <= self.vy.abs() {
102+
return false;
103+
}
104+
true
105+
}
106+
107+
pub fn hypot_to(&self, mut x: i32, mut y: i32) -> i32 {
108+
x -= self.x;
109+
y -= self.y;
110+
x * x + y * y
111+
}
112+
}
113+
114+
////////////////////////////////////////////////////////////////////////////////////////////////////
115+
116+
#[derive(PartialEq, Copy, Clone, Debug)]
117+
struct BinaryHeapState {
118+
cst: i32,
119+
pv: PosVel,
120+
}
121+
122+
impl PartialOrd for BinaryHeapState {
123+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
124+
other.cst.partial_cmp(&self.cst)
125+
}
126+
}
127+
128+
impl Eq for BinaryHeapState {}
129+
130+
impl Ord for BinaryHeapState {
131+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
132+
self.partial_cmp(other).unwrap()
133+
}
134+
}
135+
136+
////////////////////////////////////////////////////////////////////////////////////////////////////
137+
138+
struct Router {
139+
mem: Vec<Vec<Vec<Vec<(i32, PosVel)>>>>,
140+
}
141+
142+
impl Router {
143+
fn new() -> Self {
144+
Self {
145+
mem: vec![vec![vec![vec![(i32::MAX, PosVel::new_empty()); (SIZE_OUTER * 2) as usize]; (SIZE_OUTER * 2) as usize]; (MAX_V * 2) as usize]; (MAX_V * 2) as usize],
146+
}
147+
}
148+
149+
fn get(&self, s: &PosVel) -> &(i32, PosVel) {
150+
&self.mem[(s.vy + MAX_V) as usize][(s.vx + MAX_V) as usize][(s.y + SIZE_OUTER) as usize][(s.x + SIZE_OUTER) as usize]
151+
}
152+
153+
fn set(&mut self, s: &PosVel, value: (i32, PosVel)) {
154+
self.mem[(s.vy + MAX_V) as usize][(s.vx + MAX_V) as usize][(s.y + SIZE_OUTER) as usize][(s.x + SIZE_OUTER) as usize] = value;
155+
}
156+
157+
/// 次にするべき加速を返す
158+
///
159+
/// TODO: memを毎回初期化するのをやめる
160+
/// TODO: a starにする
161+
/// TODO: 早くなったらvelocity上限あげたい
162+
fn get_next_move(&mut self, sx: i32, sy: i32, vx: i32, vy: i32, tx: i32, ty: i32) -> ((i32, i32), i32) {
163+
// TODO: これ消したい
164+
self.mem = vec![vec![vec![vec![(i32::MAX, PosVel::new_empty()); (SIZE_OUTER * 2) as usize]; (SIZE_OUTER * 2) as usize]; (MAX_V * 2) as usize]; (MAX_V * 2) as usize];
165+
166+
let mut que = std::collections::BinaryHeap::new();
167+
let pv = PosVel::new(sx, sy, vx, vy);
168+
self.set(&pv, (0, PosVel::new_empty()));
169+
que.push(BinaryHeapState {
170+
cst: 0,
171+
pv,
172+
});
173+
174+
let mut best_entry = (i32::MAX, i32::MAX, PosVel::new_empty());
175+
while let Some(s) = que.pop() {
176+
let hypot = s.pv.hypot_to(tx, ty);
177+
if s.cst > 0 && (hypot, s.cst) < (best_entry.0, best_entry.1) {
178+
// s.cst == 0を除外するのは、これを入れちゃうと、離れるしかないときにすぐ虚無になっちゃうから
179+
best_entry = (hypot, s.cst, s.pv);
180+
}
181+
182+
if s.cst >= STEP_LIMIT {
183+
continue;
184+
}
185+
186+
for dvx in -2..2 {
187+
for dvy in -2..2 {
188+
let cst = s.cst + 1;
189+
let pv = s.pv.apply_gravity().accelerate_and_move(dvx, dvy);
190+
191+
if !pv.is_in_valid_area() || self.get(&pv).0 <= cst {
192+
continue;
193+
}
194+
195+
self.set(&pv, (cst, s.pv));
196+
que.push(BinaryHeapState { cst, pv });
197+
}
198+
}
199+
}
200+
201+
// 復元するよー
202+
let mut posvels = vec![];
203+
let mut last_posvel = best_entry.2;
204+
while !last_posvel.is_empty() {
205+
posvels.push(last_posvel);
206+
last_posvel = self.get(&last_posvel).1;
207+
}
208+
posvels.reverse();
209+
dbg!(&posvels);
210+
211+
let dvx;
212+
let dvy;
213+
if posvels.len() < 2 {
214+
dvx = 0;
215+
dvy = 0;
216+
} else {
217+
dvx = posvels[1].vx - posvels[0].vx;
218+
dvy = posvels[1].vy - posvels[0].vy;
219+
}
220+
let (gx, gy) = posvels[0].get_gravity();
221+
222+
((dvx - gx, dvy - gy), best_entry.1)
223+
}
224+
}
225+
226+
////////////////////////////////////////////////////////////////////////////////////////////////////
227+
228+
impl From<&Ship> for PosVel {
229+
fn from(s: &Ship) -> Self {
230+
Self {
231+
x: s.pos.0,
232+
y: s.pos.1,
233+
vx: s.v.0,
234+
vy: s.v.1,
235+
}
236+
}
237+
}
238+
239+
fn get_ship(resp: &Response, id: i32) -> &Ship {
240+
for ship in &resp.state.ships {
241+
if ship.id == id {
242+
return ship;
243+
}
244+
}
245+
panic!()
246+
}
247+
248+
fn get_next_pos(ship: &Ship) -> (i32, i32) {
249+
(ship.pos.0 + ship.v.0, ship.pos.1 + ship.v.1)
250+
}
251+
252+
fn run() {
253+
let mut router = Router::new();
254+
/*
255+
router.get_next_move(50, 50, 0, 0, -50, -50);
256+
router.get_next_move(30, 30, 0, 0, -20, -20);
257+
return;
258+
*/
259+
260+
let server_url = std::env::args().nth(1).unwrap();
261+
let mut client = Client::new(server_url);
262+
if std::env::args().len() == 2 {
263+
client.send("[1, 0]");
264+
return;
265+
}
266+
let player_key = std::env::args().nth(2).unwrap();
267+
268+
client.join(&player_key);
269+
270+
// TODO: sideによってトータル変える
271+
let cool = 16;
272+
let mut resp = client.start(448 - cool * 12 - 1 * 2, 0, cool, 1);
273+
274+
let my_id = resp.state.ships.iter().find_map(|s| if s.role == resp.info.role { Some(s.id) } else { None }).unwrap();
275+
let en_id = 1 - my_id; // TODO: 分裂したらやばい・・・・・・しらない・・・・・・
276+
277+
while resp.stage != 2 {
278+
let my_ship = get_ship(&resp, my_id);
279+
let en_ship = get_ship(&resp, en_id);
280+
281+
dbg!(my_ship);
282+
dbg!(en_ship);
283+
284+
let tx = clip_pos(en_ship.pos.0);
285+
let ty = clip_pos(en_ship.pos.1);
286+
let (_, n_steps) = router.get_next_move(my_ship.pos.0, my_ship.pos.1, my_ship.v.0, my_ship.v.1, tx, ty);
287+
288+
let tx = clip_pos(en_ship.pos.0 + n_steps * en_ship.v.0);
289+
let ty = clip_pos(en_ship.pos.1 + n_steps * en_ship.v.1);
290+
let ((dvx, dvy), _) = router.get_next_move(my_ship.pos.0, my_ship.pos.1, my_ship.v.0, my_ship.v.1, tx, ty);
291+
let mut commands = vec![Command::Accelerate(my_id, (-dvx, -dvy))];
292+
293+
// 次ステップのポジで重なるなら爆発!
294+
let myp = PosVel::from(my_ship).apply_gravity().accelerate_and_move(dvx, dvy);
295+
let enp = PosVel::from(en_ship).apply_gravity().accelerate_and_move(0, 0);
296+
if myp.x == enp.x && myp.y == enp.y {
297+
eprintln!("{}", "BOMB!!!!!!!!".repeat(10));
298+
commands.push(Command::Detonate(my_id));
299+
}
300+
301+
dbg!((dvx, dvy));
302+
resp = client.command(&commands);
303+
}
304+
}
305+
306+
fn main() {
307+
let _ = ::std::thread::Builder::new()
308+
.name("run".to_string())
309+
.stack_size(32 * 1024 * 1024)
310+
.spawn(run)
311+
.unwrap()
312+
.join();
313+
}

0 commit comments

Comments
 (0)