chiark / gitweb /
deck: Skeleton
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 22 Mar 2021 02:47:55 +0000 (02:47 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Mon, 22 Mar 2021 19:14:05 +0000 (19:14 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/deck.rs [new file with mode: 0644]
src/lib.rs
src/spec.rs

diff --git a/src/deck.rs b/src/deck.rs
new file mode 100644 (file)
index 0000000..52adc9b
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2020-2021 Ian Jackson and contributors to Otter
+// SPDX-License-Identifier: AGPL-3.0-or-later
+// There is NO WARRANTY.
+
+// This is otter::hidden::magic
+
+use crate::prelude::*;
+
+pub const ACTIVE_DESC: &str = "a pickup deck (active)";
+pub const INACTIVE_DESC: &str = "a pickup deck (inactive)";
+
+#[derive(Debug,Serialize,Deserialize)]
+struct Deck {
+  shape: GenericSimpleShape<(), Outline>,
+}
+
+#[dyn_upcast]
+impl OutlineTrait for Deck {
+  delegate!{
+    to self.shape {
+      fn outline_path(&self, scale: f64) -> Result<Html,IE>;
+      fn thresh_dragraise(&self) -> Result<Option<Coord>,IE>;
+      fn bbox_approx(&self) -> Result<[Pos;2], IE>;
+    }
+  }
+}
+
+#[typetag::serde(name="PickupDeck")]
+impl PieceSpec for piece_specs::Deck {
+  #[throws(SpecError)]
+  fn load(&self, _: usize, _: &mut GPiece, _ir: &InstanceRef)
+          -> PieceSpecLoaded {
+    let common = SimpleCommon {
+      itemname: None,
+      faces: self.faces.clone(),
+      edges: self.edges.clone(),
+      edge_width: self.edge_width,
+    };
+    let shape = GenericSimpleShape::new(
+      (),
+      self.shape.clone(),
+      "magic-pickupdeck",
+      &common)?;
+    if shape.count_faces() != 2 {
+      throw!(SpE::WrongNumberOfFaces);
+    }
+    let p = Box::new(Deck {
+      shape,
+    }) as Box<dyn PieceTrait>;
+    PieceSpecLoaded { p, occultable: None }
+  }
+}
+
+impl Deck {
+  fn active(&self, gpc: &GPiece) -> bool {
+    gpc.occult.is_active()
+  }
+
+  fn current_face(&self, gpc: &GPiece) -> FaceId {
+    (self.active(gpc) as RawFaceId).into()
+  }
+}
+
+#[typetag::serde]
+impl PieceTrait for Deck {
+  fn nfaces(&self) -> RawFaceId { 1 }
+  #[throws(IE)]
+  fn svg_piece(&self, f: &mut Html, gpc: &GPiece,
+               _gs: &GameState, _vpid: VisiblePieceId) {
+    let face = self.current_face(gpc);
+    self.shape.svg_piece_raw(f, face, &mut |_|Ok::<_,IE>(()))?;
+  }
+
+  #[throws(IE)]
+  fn describe_html(&self, gpc: &GPiece) -> Html {
+    Html::lit(
+      if self.active(gpc) { ACTIVE_DESC } else { INACTIVE_DESC }
+    )
+  }
+
+  delegate!{
+    to self.shape {
+      fn itemname(&self) -> &str;
+    }
+  }
+
+  #[throws(InternalError)]
+  fn add_ui_operations(&self, upd: &mut Vec<UoDescription>,
+                       _gs: &GameState, gpc: &GPiece) {
+    upd.push(
+      if self.active(gpc) {
+        UoDescription {
+          kind: UoKind::Piece,
+          def_key: 'A',
+          opname: "activate".to_owned(),
+          desc: Html::lit("Enable pickup deck (to shuffle, etc.)"),
+          wrc: WRC::Unpredictable,
+        }
+      } else {
+        UoDescription {
+          kind: UoKind::Piece,
+          def_key: 'S',
+          opname: "deactivate".to_owned(),
+          desc: Html::lit("Deactivate pickup deck"),
+          wrc: WRC::Unpredictable,
+        }
+      }
+    )
+  }
+}
index 1703862cd1cd4314bb8a3b99e92c888e9118f79b..5ddbdc100633de61338e6f65ee8cb4a88803cc99 100644 (file)
@@ -13,6 +13,7 @@ pub mod authproofs;
 pub mod clock;
 pub mod commands;
 pub mod config;
+pub mod deck;
 pub mod debugreader;
 pub mod error;
 pub mod gamestate;
index e0b4d8e43c0bc8435cdb5210b20ee3a492abac38..6871ddd94ed1df1cfc92b549e42bb612c7f859ff 100644 (file)
@@ -81,6 +81,7 @@ pub enum SpecError {
   CompassAngleInvalid,
   ZeroFaces,
   InconsistentFacesEdgecoloursCount,
+  WrongNumberOfFaces,
   SpecifiedWidthOfNoEdges,
   UnsupportedShape,
   NegativeTimeout,
@@ -246,6 +247,14 @@ pub mod piece_specs {
     pub edge_width: Option<f64>,
     pub shape: Outline,
   }
+
+  #[derive(Debug,Serialize,Deserialize)]
+  pub struct Deck {
+    pub faces: IndexVec<FaceId, ColourSpec>,
+    #[serde(default)] pub edges: IndexVec<FaceId, ColourSpec>,
+    pub edge_width: Option<f64>,
+    pub shape: Outline,
+  }
 }
 
 //---------- Pos ----------