From 7c2cd82b7bc8db00af140885b64c0d53b802c144 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 11 Mar 2021 14:20:30 +0000 Subject: [PATCH] hidden: Permute pieces only within same occult ilk Signed-off-by: Ian Jackson --- src/hidden.rs | 71 +++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/hidden.rs b/src/hidden.rs index c89f26d5..1d2a90c9 100644 --- a/src/hidden.rs +++ b/src/hidden.rs @@ -396,41 +396,52 @@ mod vpid { gplayers: &mut GPlayers, gpieces: &mut GPieces, ipieces: &IPieces) { - // xxx take account of occult ilks - - // We must permute for if we have any views that are scrambled - // or displaced obviously. For invisible too, so that when they - // reappear the ids have been permuted. And that's all the - // non-Visible views which an occultation ought to have at least - // one of... - // - // We choose a single permutation of the pieces in the - // Occultation::notches. - - let permu = { - let mut permu: Vec<_> = - occ.notches.table.iter() - .filter_map(NR::piece) - .collect(); - - let mut rng = thread_rng(); - permu.shuffle(&mut rng); - permu - }; - let new_notches = { - let mut permus = permu.iter(); - let new_notches = occ.notches.table.iter().map(|nr| match nr { - &f@ NR::Free(_) => f, - NR::Piece(p) => NR::Piece(*permus.next().unwrap()), - }) - .collect::>(); - permus.next().map(|x| panic!("{:?}", x)); + + let mut ilks: HashMap, + Vec, + )> = HashMap::new(); + + for (notch, nr) in occ.notches.table.iter_enumerated() { + let piece = if let Some(p) = nr.piece() { p } else { continue }; + let occilk = (|| Some(ipieces.get(piece)?.occilk.as_ref()?))(); + let occilk = if let Some(o) = occilk { *o.borrow() } else { + error!("{}", internal_error_bydebug(&(occid, &occ, &nr, piece))); + continue; + }; + let (notches, pieces) = ilks.entry(occilk).or_default(); + notches.push(notch); + pieces.push(piece); + } + + let mut new_notches = index_vec![]; + for (_occilk, (notches, pieces)) in ilks { + // We must permute for if we have any views that are scrambled + // or displaced obviously. For invisible too, so that when they + // reappear the ids have been permuted. And that's all the + // non-Visible views which an occultation ought to have at least + // one of... + // + // We choose a single permutation of each of the subsets (for a + // partiular ilk) of the pieces in the Occultation::notches. + + let permu = { + let mut permu = pieces; + let mut rng = thread_rng(); + permu.shuffle(&mut rng); + permu + }; + + for (notch, new_piece) in itertools::zip_eq(notches, permu) { + new_notches[notch] = NR::Piece(new_piece); + } + } + new_notches }; for gpl in gplayers.values_mut() { - // xxx don't do this for Visible, check occk let mut fwd_updates = vec![]; -- 2.30.2