chiark / gitweb /
delete_piece: Break out into global.rs
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 1 May 2022 11:19:35 +0000 (12:19 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 1 May 2022 12:00:58 +0000 (13:00 +0100)
fastsplit deletion is going to want this.  This may not be in its
final form, particularly because of ToRecalculate, which fastsplit
doesn't have one of yet.

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
daemon/cmdlistener.rs
src/global.rs

index 6745b26040cd5ea3bbda4bcb93c3cb5533945193..a3c1a550abcf78f80bde7c70b2522515848fcaa1 100644 (file)
@@ -1012,45 +1012,21 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
     },
 
     MGI::DeletePiece(piece) => {
-      let (ig_g, modperm, _) = cs.check_acl_modify_pieces(ag, ig)?;
-      let ig = &mut **ig_g;
+      let (ig, modperm, _) = cs.check_acl_modify_pieces(ag, ig)?;
       let _ipc = ig.ipieces.as_mut(modperm)
         .get(piece).ok_or(ME::PieceNotFound)?;
-      let gs = &mut ig.gs;
-      let gpc = gs.pieces.as_mut(modperm).get_mut(piece);
-      let mut xupdates = vec![];
-      if let Some(gpc) = gpc {
-        gpc.occult.passive_delete_hook(&mut gs.occults, piece);
-        if gpc.occult.is_active() {
-          xupdates.append(
-            &mut
-              remove_occultation(
-                &mut gs.gen.unique_gen(),
-                &mut gs.players,
-                &mut gs.pieces,
-                &mut gs.occults,
-                &ig.ipieces,
-                &ig.ioccults,
-                to_permute,
-                piece)?
-          );
-        }
-      }
-      let ioccults = &ig.ioccults;
-      let gpc = gs.pieces.as_mut(modperm).remove(piece);
-      let ipc = ig.ipieces.as_mut(modperm).remove(piece).unwrap();
-      let desc_html = if let Some(gpc) = &gpc {
-        let pri = PieceRenderInstructions::new_visible(default());
-        pri.describe(ioccults,&gs.occults, gpc, &ipc)
-      } else {
-        "<piece partially missing from game state>".to_html()
-      };
-      if let Some(gpc) = gpc {
-        ipc.p.into_inner().delete_hook(&gpc, gs);
-      }
-      if let Some(occilk) = ipc.occilk {
-        ig.ioccults.ilks.dispose_iilk(occilk);
-      }
+
+      let (desc_html, xupdates) =
+        ig.delete_piece(modperm, to_permute, piece,
+                        |ioccults, goccults, ipc, gpc| {
+          if let (Some(ipc), Some(gpc)) = (ipc, gpc) {
+            let pri = PieceRenderInstructions::new_visible(default());
+            pri.describe(ioccults,goccults, gpc, &ipc)
+          } else {
+            "<piece partially missing from game state>".to_html()
+          }
+        })?;
+
       (U{ pcs: vec![(piece, PieceUpdateOp::Delete())],
           log: vec![ LogEntry {
             html: hformat!("A piece {} was removed from the game",
@@ -1058,9 +1034,9 @@ fn execute_game_insn<'cs, 'igr, 'ig: 'igr>(
           }],
           raw: None },
        Fine,
-       xupdates.into_unprepared(None),
+       xupdates,
        vec![],
-       ig_g)
+       ig)
     },
 
     MGI::AddPieces(PiecesSpec{ pos,posd,count,face,pinned,angle,info }) => {
index 11da90edcbd2b537b40495980f907005f85a3967..02ec316997a503ba952fbb96032c705e3eda9fb5 100644 (file)
@@ -641,6 +641,55 @@ impl<Id> InstanceAccessDetails<Id>
 }
 
 impl<'ig> InstanceGuard<'ig> {
+  /// Idempotent.
+  #[throws(IE)]
+  pub fn delete_piece<H,T>(&mut self, modperm: ModifyingPieces,
+                             to_permute: &mut ToRecalculate,
+                             piece: PieceId, hook: H)
+                             -> (T, UnpreparedUpdates)
+  where H: FnOnce(&IOccults, &GOccults,
+                  Option<&IPiece>, Option<&GPiece>) -> T
+  {
+    let ig = &mut **self;
+    let gs = &mut ig.gs;
+    let gpc = gs.pieces.as_mut(modperm).get_mut(piece);
+    let mut xupdates = vec![];
+    if let Some(gpc) = gpc {
+      gpc.occult.passive_delete_hook(&mut gs.occults, piece);
+      if gpc.occult.is_active() {
+        xupdates.append(
+          &mut
+            remove_occultation(
+              &mut gs.gen.unique_gen(),
+              &mut gs.players,
+              &mut gs.pieces,
+              &mut gs.occults,
+              &ig.ipieces,
+              &ig.ioccults,
+              to_permute,
+              piece)?
+        );
+      }
+    }
+    let ioccults = &ig.ioccults;
+    let gpc = gs.pieces.as_mut(modperm).remove(piece);
+    let ipc = ig.ipieces.as_mut(modperm).remove(piece);
+
+    let hook_r = hook(ioccults, &gs.occults,
+                      ipc.as_ref(), gpc.as_ref());
+
+    if let Some(ipc) = ipc {
+      if let Some(gpc) = gpc {
+        ipc.p.into_inner().delete_hook(&gpc, gs);
+      }
+      if let Some(occilk) = ipc.occilk {
+        ig.ioccults.ilks.dispose_iilk(occilk);
+      }
+    }
+
+    (hook_r, xupdates.into_unprepared(None))
+  }
+
   /// caller is responsible for logging; threading it through
   /// proves the caller has a log entry.
   #[throws(MgmtError)]