New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tank can move to tile already occupied by invisible infantry #106

Closed
ozkriff opened this Issue Sep 28, 2015 · 16 comments

Comments

2 participants
@ozkriff
Owner

ozkriff commented Sep 28, 2015

@ozkriff ozkriff added the t-bug label Sep 28, 2015

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 4, 2015

Owner

"fixed" - tank can not move there anymore, but "Bad command: BadPath" message is printed to stdout.

Owner

ozkriff commented Dec 4, 2015

"fixed" - tank can not move there anymore, but "Bad command: BadPath" message is printed to stdout.

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 22, 2015

Owner

Наверное, пускай в такой ситуации враг просто становится обнаруженным. Хоть разумно будет выглядеть.

Owner

ozkriff commented Dec 22, 2015

Наверное, пускай в такой ситуации враг просто становится обнаруженным. Хоть разумно будет выглядеть.

@Vinatorul

This comment has been minimized.

Show comment
Hide comment
@Vinatorul

Vinatorul Dec 22, 2015

@ozkriff думаю ещё разумно будет тратить очко хода в этом случае

@ozkriff думаю ещё разумно будет тратить очко хода в этом случае

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 22, 2015

Owner

Согласен)

Owner

ozkriff commented Dec 22, 2015

Согласен)

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 24, 2015

Owner

Только хз как это правильнее реализовать =\ Уменьшение у отряда очков движения у меня пока намертво связано с событием движения, а тут никто никуда не двигается. Так что надо менять систему событий, а это я бы пока отложил, ибо уже серьезная штука.

Owner

ozkriff commented Dec 24, 2015

Только хз как это правильнее реализовать =\ Уменьшение у отряда очков движения у меня пока намертво связано с событием движения, а тут никто никуда не двигается. Так что надо менять систему событий, а это я бы пока отложил, ибо уже серьезная штука.

@Vinatorul

This comment has been minimized.

Show comment
Hide comment
@Vinatorul

Vinatorul Dec 24, 2015

Можно, например, сделать движение на ту клетку и сразу отход обратно.

  • Отряд перешел в клетку
  • Обнаружил засаду врага
  • Сразу отступил назад

Можно, например, сделать движение на ту клетку и сразу отход обратно.

  • Отряд перешел в клетку
  • Обнаружил засаду врага
  • Сразу отступил назад

@ozkriff ozkriff removed the s-in-progress label Jan 29, 2016

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Jan 29, 2016

Owner

Откладывается до перехода к трехслотовой системе

Owner

ozkriff commented Jan 29, 2016

Откладывается до перехода к трехслотовой системе

@ozkriff ozkriff added the s-active label Sep 8, 2016

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 12, 2016

Owner

Уже почти год прошел, наверное пора бы чего-то с этим сделать.

Owner

ozkriff commented Dec 12, 2016

Уже почти год прошел, наверное пора бы чего-то с этим сделать.

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 13, 2016

Owner

В чем, собственно, сейчас косяк:

Есть вот такая функция для проверки адекватности команды:

pub fn check_command<S: GameState>(
    db: &Db,
    player_id: PlayerId,
    state: &S,
    command: &Command,
) -> Result<(), CommandError> {...}

Она отлично работает в визуализаторе, когда ей передается PartialState конкретного игрока.

Но вот внутри ядра эта функция работает с InternalState, которому известно все и где нет никакого тумана войны. И если команда движения в клетку, где на самом деле сидит враг, проходит проверку в визуализаторе, то в ядре проверка натыкается на вражеский отряд и ругается что команда кривая.

Настоящего PartialState в ядре нет, ядро хранит "истинный" InternalState со всей инфой и Fow для каждого из игроков (нужны для фильтрации событий).

Итак, какой выход?

Придется таки запилить свою старою мысль (https://github.com/ozkriff/zoc/blob/0ce21f26c/core/src/filter.rs#L62) TmpPartialState - это как обычный PartialState, только он временный и создается из пары ссылок:

struct TmpPartialState<'a> {
    state: &'a InternalState,
    fow: &'a Fow,
}

fn new(state: &'a InternalState, fow: &'a Fow) -> TmpPartialState<'a> {
    TmpPartialState {
        state: state,
        fow: fow,
    }
}

В этой штуке надо будет вставить код во все функции, который будет выкидывать отряды (и что там еще?), которые не должны быть видны из-за тумана войны.

Возможно, заодно получится код core/src/filter.rs причесать.

Owner

ozkriff commented Dec 13, 2016

В чем, собственно, сейчас косяк:

Есть вот такая функция для проверки адекватности команды:

pub fn check_command<S: GameState>(
    db: &Db,
    player_id: PlayerId,
    state: &S,
    command: &Command,
) -> Result<(), CommandError> {...}

Она отлично работает в визуализаторе, когда ей передается PartialState конкретного игрока.

Но вот внутри ядра эта функция работает с InternalState, которому известно все и где нет никакого тумана войны. И если команда движения в клетку, где на самом деле сидит враг, проходит проверку в визуализаторе, то в ядре проверка натыкается на вражеский отряд и ругается что команда кривая.

Настоящего PartialState в ядре нет, ядро хранит "истинный" InternalState со всей инфой и Fow для каждого из игроков (нужны для фильтрации событий).

Итак, какой выход?

Придется таки запилить свою старою мысль (https://github.com/ozkriff/zoc/blob/0ce21f26c/core/src/filter.rs#L62) TmpPartialState - это как обычный PartialState, только он временный и создается из пары ссылок:

struct TmpPartialState<'a> {
    state: &'a InternalState,
    fow: &'a Fow,
}

fn new(state: &'a InternalState, fow: &'a Fow) -> TmpPartialState<'a> {
    TmpPartialState {
        state: state,
        fow: fow,
    }
}

В этой штуке надо будет вставить код во все функции, который будет выкидывать отряды (и что там еще?), которые не должны быть видны из-за тумана войны.

Возможно, заодно получится код core/src/filter.rs причесать.

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 13, 2016

Owner

В этой штуке надо будет вставить код во все функции, который будет выкидывать отряды (и что там еще?), которые не должны быть видны из-за тумана войны.

И тут возникает проблема - интерфейс типажа GameState:

. . .
    fn units(&self) -> &HashMap<UnitId, Unit>;
    fn objects(&self) -> &HashMap<ObjectId, Object>;
    fn sectors(&self) -> &HashMap<SectorId, Sector>;
. . .

Эти функции возвращают ссылку на HashMap. Я с самого начала знал что это плохая идея :( .

Мне в TmpPartialState нужно фильтровать как минимум отряды, но при текущем интерфейсе я этого делать вообще никак не могу - функция fn units(&self) -> &HashMap<UnitId, Unit> принимает &self по простой неизменяемой ссылке, и HashMap возвращает по такой же ссылке. Т.е. я даже создать новый HashMap и вернуть его не могу - кто его хранить-то будет?

Для чего мне нужно было возвращать ссылку на HashMap?

  1. для удобной итерации по всем отрядам
  2. для проверки наличия отряда с определенным идентификатором и получения доступа к нему

Придется для первого использования завести функцию, которая будет возвращать итератор, а для второго сделать какой-то отдельный unit_opt. Не очень-то удобно выходит, но больше вариантов не вижу.

Owner

ozkriff commented Dec 13, 2016

В этой штуке надо будет вставить код во все функции, который будет выкидывать отряды (и что там еще?), которые не должны быть видны из-за тумана войны.

И тут возникает проблема - интерфейс типажа GameState:

. . .
    fn units(&self) -> &HashMap<UnitId, Unit>;
    fn objects(&self) -> &HashMap<ObjectId, Object>;
    fn sectors(&self) -> &HashMap<SectorId, Sector>;
. . .

Эти функции возвращают ссылку на HashMap. Я с самого начала знал что это плохая идея :( .

Мне в TmpPartialState нужно фильтровать как минимум отряды, но при текущем интерфейсе я этого делать вообще никак не могу - функция fn units(&self) -> &HashMap<UnitId, Unit> принимает &self по простой неизменяемой ссылке, и HashMap возвращает по такой же ссылке. Т.е. я даже создать новый HashMap и вернуть его не могу - кто его хранить-то будет?

Для чего мне нужно было возвращать ссылку на HashMap?

  1. для удобной итерации по всем отрядам
  2. для проверки наличия отряда с определенным идентификатором и получения доступа к нему

Придется для первого использования завести функцию, которая будет возвращать итератор, а для второго сделать какой-то отдельный unit_opt. Не очень-то удобно выходит, но больше вариантов не вижу.

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 14, 2016

Owner

Мде, просто так итератор возвращать нельзя, потому что в TmpPartialState нужно фильтровать невидимые отряды, а это с текущим интерфейсом не сделать (hashmap.iter().filter() возвращает вообще другой тип, а impl Trait так пока и не стабилизирован).

Если на форуме ничего более простого не подскажут, то придется накручивать свои итераторы:

https://play.rust-lang.org/?gist=eda616da6aef9bfde53855a53784dd48

Owner

ozkriff commented Dec 14, 2016

Мде, просто так итератор возвращать нельзя, потому что в TmpPartialState нужно фильтровать невидимые отряды, а это с текущим интерфейсом не сделать (hashmap.iter().filter() возвращает вообще другой тип, а impl Trait так пока и не стабилизирован).

Если на форуме ничего более простого не подскажут, то придется накручивать свои итераторы:

https://play.rust-lang.org/?gist=eda616da6aef9bfde53855a53784dd48

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 15, 2016

Owner

Лучше своих итераторов так ничего и не пришло в голову. Была сложность с временами жизни, но с этим на форуме как раз помогли:

... можно изменить функцию типажа State чтобы она брала self по значению, а не по ссылке. А имплементацию делать для ссылки &'a FullState<'a>.

В итоге такой вариант в основной код буду пытаться перенести:

https://play.rust-lang.org/?gist=0aae6d1137df9c521b24927e52bafe1a

Owner

ozkriff commented Dec 15, 2016

Лучше своих итераторов так ничего и не пришло в голову. Была сложность с временами жизни, но с этим на форуме как раз помогли:

... можно изменить функцию типажа State чтобы она брала self по значению, а не по ссылке. А имплементацию делать для ссылки &'a FullState<'a>.

В итоге такой вариант в основной код буду пытаться перенести:

https://play.rust-lang.org/?gist=0aae6d1137df9c521b24927e52bafe1a

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 15, 2016

Owner

Попробовал вставить гист выше в реальный код и напоролся еще на ряд косяков.

Во первых, если я пытаюсь добавить в свой супер-пупер типаж метод по получению ссылки на конкретный объект (а в реальном коде мне оно нужно)

 trait State {
    type Iter: Iterator;

    fn objects(self) -> Self::Iter;

    fn object(self, id: i32) -> &Object; // <- вот этот
}

то я получаю:

 error[E0106]: missing lifetime specifier
  --> <anon>:11:33
   |
11 |     fn object(self, id: i32) -> &Object;
   |                                 ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
   = help: consider giving it an explicit bounded or 'static lifetime

И это намекает что таки не выйдет обойтись без явных ВЖ.

Во вторых, я ничего не могу сделать с этим своим итератором, если нет доступа к оригинальному типу:

 fn foo<S: State>(state: &S) {
    for (id, object) in state.objects() {
        println!("{:?} -> {:?}", id, object);
    }
}
 error[E0308]: mismatched types
  --> <anon>:80:9
   |
80 |     for (id, object) in state.objects() {
   |         ^^^^^^^^^^^^ expected associated type, found tuple
   |
   = note: expected type `<<S as State>::Iter as std::iter::Iterator>::Item`
   = note:    found type `(_, _)`

Как-то я в растерянности, как тут из итераторов вытащить что мне надо тоже не уверен.

Owner

ozkriff commented Dec 15, 2016

Попробовал вставить гист выше в реальный код и напоролся еще на ряд косяков.

Во первых, если я пытаюсь добавить в свой супер-пупер типаж метод по получению ссылки на конкретный объект (а в реальном коде мне оно нужно)

 trait State {
    type Iter: Iterator;

    fn objects(self) -> Self::Iter;

    fn object(self, id: i32) -> &Object; // <- вот этот
}

то я получаю:

 error[E0106]: missing lifetime specifier
  --> <anon>:11:33
   |
11 |     fn object(self, id: i32) -> &Object;
   |                                 ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
   = help: consider giving it an explicit bounded or 'static lifetime

И это намекает что таки не выйдет обойтись без явных ВЖ.

Во вторых, я ничего не могу сделать с этим своим итератором, если нет доступа к оригинальному типу:

 fn foo<S: State>(state: &S) {
    for (id, object) in state.objects() {
        println!("{:?} -> {:?}", id, object);
    }
}
 error[E0308]: mismatched types
  --> <anon>:80:9
   |
80 |     for (id, object) in state.objects() {
   |         ^^^^^^^^^^^^ expected associated type, found tuple
   |
   = note: expected type `<<S as State>::Iter as std::iter::Iterator>::Item`
   = note:    found type `(_, _)`

Как-то я в растерянности, как тут из итераторов вытащить что мне надо тоже не уверен.

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 16, 2016

Owner

Новый хитрожопый вариант: https://play.rust-lang.org/?gist=746a60bce4fe06dede32104f99f5f2fb

И еще более хитрожопый: https://play.rust-lang.org/?gist=b5cf2366785848bb02b304799979cdfd

Owner

ozkriff commented Dec 16, 2016

Новый хитрожопый вариант: https://play.rust-lang.org/?gist=746a60bce4fe06dede32104f99f5f2fb

И еще более хитрожопый: https://play.rust-lang.org/?gist=b5cf2366785848bb02b304799979cdfd

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Dec 20, 2016

Owner

Наколбасил в ветке кривоватый, но более-менее рабочий вариант. Пришлось сильно изувечить туман войны, ввести FullState и еще много все вивисектировать.

Пришлось добавить новый тип события - Reveal. Потому что Show предназначен только для генерации в фильтре.

Теперь причесываю код в RC ветку.


Owner

ozkriff commented Dec 20, 2016

Наколбасил в ветке кривоватый, но более-менее рабочий вариант. Пришлось сильно изувечить туман войны, ввести FullState и еще много все вивисектировать.

Пришлось добавить новый тип события - Reveal. Потому что Show предназначен только для генерации в фильтре.

Теперь причесываю код в RC ветку.


ozkriff added a commit that referenced this issue Dec 22, 2016

@ozkriff ozkriff closed this Dec 22, 2016

@ozkriff

This comment has been minimized.

Show comment
Hide comment
@ozkriff

ozkriff Jan 9, 2017

Owner

Проверил как такие ситуации решены в Battle Academy 2 - техника тупо не выполняет приказ движения в клетку со скрытым врагом, без какого-то отображения причины в интерфейсе. Выглядит странновато.

Owner

ozkriff commented Jan 9, 2017

Проверил как такие ситуации решены в Battle Academy 2 - техника тупо не выполняет приказ движения в клетку со скрытым врагом, без какого-то отображения причины в интерфейсе. Выглядит странновато.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment