Skip to content
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
Closed

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

ozkriff opened this issue Sep 28, 2015 · 16 comments
Labels

Comments

@ozkriff
Copy link
Owner

@ozkriff ozkriff commented Sep 28, 2015

@ozkriff ozkriff added the t-bug label Sep 28, 2015
@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 4, 2015

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

@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 22, 2015

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

@Vinatorul
Copy link

@Vinatorul Vinatorul commented Dec 22, 2015

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

@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 22, 2015

Согласен)

@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 24, 2015

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

@Vinatorul
Copy link

@Vinatorul Vinatorul commented Dec 24, 2015

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

  • Отряд перешел в клетку
  • Обнаружил засаду врага
  • Сразу отступил назад
@ozkriff ozkriff removed the s-in-progress label Jan 29, 2016
@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Jan 29, 2016

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

@ozkriff ozkriff added the s-active label Sep 8, 2016
@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 12, 2016

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

@ozkriff
Copy link
Owner Author

@ozkriff 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
Copy link
Owner Author

@ozkriff 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
Copy link
Owner Author

@ozkriff ozkriff commented Dec 14, 2016

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

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

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

@ozkriff
Copy link
Owner Author

@ozkriff ozkriff commented Dec 15, 2016

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

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

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

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

@ozkriff
Copy link
Owner Author

@ozkriff 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
Copy link
Owner Author

@ozkriff ozkriff commented Dec 16, 2016

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

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

@ozkriff
Copy link
Owner Author

@ozkriff 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
Copy link
Owner Author

@ozkriff 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
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.