ozkriff / zoc

⬡ Zone of Control is a hexagonal turn-based strategy game written in Rust. [DISCONTINUED]
https://ozkriff.itch.io/zoc
Apache License 2.0
379 stars 31 forks source link

assertion failed in InternalState::add_unit #239

Closed adrianheine closed 7 years ago

adrianheine commented 8 years ago

With c815eb029d6cbed8847470b2d54fa205b2286084 (I think while AI enemy moved):

thread '<main>' panicked at 'assertion failed: self.units.get(&unit_info.unit_id).is_none()', core/src/internal_state.rs:228
stack backtrace:
   1:     0x563605358c8f - std::sys::backtrace::tracing::imp::write::h3800f45f421043b8
   2:     0x56360535ba9b - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h0ef6c8db532f55dc
   3:     0x56360535b723 - std::panicking::default_hook::hf3839060ccbb8764
   4:     0x56360535264d - std::panicking::rust_panic_with_hook::h5dd7da6bb3d06020
   5:     0x56360529507f - std::panicking::begin_panic::h4c14e704ed94392f
   6:     0x5636052af5ec - core::internal_state::InternalState::add_unit::hc74b1e8713abe737
   7:     0x5636052a159c - core::Core::do_core_event::h637259803bbd4608
   8:     0x5636052a66d8 - core::Core::simulation_step::haeaacd8406f42bf0
   9:     0x5636052a88a2 - core::Core::do_command::had50e6564e64caaa
  10:     0x56360526e730 - zoc::tactical_screen::TacticalScreen::handle_event_lmb_release::h8aa06200b221289d
  11:     0x5636052793f5 - _<tactical_screen..TacticalScreen as screen..Screen>::handle_event::hd894107c308b2557
  12:     0x5636052349f2 - zoc::main::h308ba5ec18216eed
  13:     0x56360535b368 - std::panicking::try::call::hbbf4746cba890ca7
  14:     0x56360536540b - __rust_try
  15:     0x5636053653ae - __rust_maybe_catch_panic
  16:     0x56360535ae0e - std::rt::lang_start::hbcefdc316c2fbd45
  17:     0x7f49e8bb12b0 - __libc_start_main
  18:     0x563605233899 - _start
  19:                0x0 - <unknown>
ozkriff commented 8 years ago

It`s hard to reproduce such errors without replays.

Blocked by https://github.com/ozkriff/zoc/issues/25

ozkriff commented 7 years ago

@adrianheine @bjorn3 @atallahade I hope it's fixed now.

I've managed to find the problem just with logs:

https://gist.github.com/ozkriff/4c08134264f95d42933b5973410d507e

The problem was the forgotten return statement in State::add_unit method. I have no idea how that whole check has slipped in :( .


Пол субботы отлаживался, в итоге нашел что я return в очень неудачном месте забыл.

Это вообще кусок какой-то старой логики из пользовательского интерфейса, но оно как-то постепенно перекочевало в самое ядро игры. Косяк был в том, что очки подкреплений проверялись и уменьшались на стоимость юнита не только при событии CreateUnit, но и при ShowUnit. Если юнит появлялся-исчезал несколько раз, то он высасывал все очки подкрепления у своего хозяина. Но только в состоянии врага хозяина. В итоге какой-то из ShowUnit из-за этого тупого return просто молча не срабатывал и состояния совсем рассинхронизировались - в Истинном Состоянии и в состоянии его хозяина юнит был, а вот у других игроков этого юнита уже могло и не быть. Ну и игра потом падала в состоянии какого-то из врагов, которому приходило событие о том, что несуществующий юнит что-то сделал.

Принтов просто немеряно добавил, пока не сообразил в чем дело:

https://gist.github.com/ozkriff/4c08134264f95d42933b5973410d507e

Хорошо что я додумался сделать "до-после" распечатки идентификаторов всех отрядов в каждом из состояний:

State 'player.before' [14 15 19 17 1 18 5 13 12 6 8 7D 9 3 10 16 ]
State 'player.after' [14 15 19 17 20 1 18 5 13 12 6 8 7D 9 3 10 16 ]

С ними при поиске в логе по идентификатору юнита, на котором все упало, сразу стало видно, что один из ShowUnit событий не приводит к появлению новых юнитов в состоянии.

В общем, сферическая в вакууме удачно завалившая логическая ошибка

ozkriff commented 7 years ago

Closing it for now