MFMv2.0.10
Movable Feast Machine Simulator 2.0.10
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Element_DBar.h
1 #ifndef ELEMENT_DBAR_H /* -*- C++ -*- */
2 #define ELEMENT_DBAR_H
3 
4 #include "Element.h"
5 #include "EventWindow.h"
6 #include "ElementTable.h"
7 #include "Element_Empty.h"
8 #include "Element_Res.h"
9 #include "itype.h"
10 #include "FXP.h"
11 #include "P1Atom.h"
12 #include "ColorMap.h"
13 
14 namespace MFM
15 {
16 
17 #define DBAR_VERSION 1
18 
19  // Forward
20  template <class CC> class Element_SBar ;
21 
58  template <class CC>
59  class Element_DBar : public Element<CC>
60  {
61  // Extract short names for parameter types
62  typedef typename CC::ATOM_TYPE T;
63  typedef typename CC::PARAM_CONFIG P;
64  enum { R = P::EVENT_WINDOW_RADIUS };
65 
66  template <u32 TVBITS>
67  static u32 toSignMag(s32 value) {
68  const u32 SIGN_BIT = 1<<(TVBITS-1);
69  const u32 MAX = SIGN_BIT-1;
70  u32 sign = 0;
71  if (value < 0) {
72  sign = SIGN_BIT;
73  value = -value;
74  }
75  if (value > MAX)
76  value = MAX;
77  u32 val = (u32) value;
78  return sign|val;
79  }
80 
81  template <u32 TVBITS>
82  static u32 toMag(u32 value) {
83  const u32 MAX = (1<<TVBITS)-1;
84  if (value < 0) {
85  FAIL(ILLEGAL_ARGUMENT);
86  }
87  if (value > MAX)
88  value = MAX;
89  u32 val = value;
90  return val;
91  }
92 
93  template <u32 TVBITS>
94  static s32 fromSignMag(const u32 value) {
95  const u32 SIGN_BIT = 1<<(TVBITS-1);
96  const u32 MASK = SIGN_BIT-1;
97  FXP16 val = value&MASK;
98  if (value & SIGN_BIT)
99  val = -val;
100  return val;
101  }
102 
103  template <u32 TVBITS>
104  static u32 fromMag(const u32 value) {
105  const u32 MASK = (1<<TVBITS)-1;
106  u32 val = value&MASK;
107  return val;
108  }
109 
110  template <u32 TXBITS, u32 TYBITS>
111  static u32 toUTiny(const UPoint & v) {
112  u32 x = toMag<TXBITS>(v.GetX());
113  u32 y = toMag<TYBITS>(v.GetY());
114  return (x<<TYBITS)|y;
115  }
116 
117  template <u32 TXBITS, u32 TYBITS>
118  static UPoint toUPoint(const u32 bits) {
119 
120  u32 x = fromMag<TXBITS>(bits>>TYBITS);
121  u32 y = fromMag<TYBITS>(bits);
122  return UPoint(x,y);
123  }
124 
125  public:
126 
127  static Element_DBar THE_INSTANCE;
128  static const u32 TYPE() {
129  return THE_INSTANCE.GetType();
130  }
131 
132  static const u32 TYPE_BITS = 15;
133 
134  static bool IsOurType(u32 type) {
135  return type==TYPE();
136  }
137 
138  static const u32 BITS_WIDE = 5;
139  static const u32 BITS_HIGH = 7;
140  static const u32 BITS_SYMI = 3;
141 
142  static const u32 BITS_BAR_COORD_LEN = BITS_WIDE + BITS_HIGH;
143 
144  static const u32 STATE_SIZE_IDX = 0;
145  static const u32 STATE_SIZE_LEN = BITS_BAR_COORD_LEN;
146  static const u32 STATE_POS_IDX = STATE_SIZE_IDX + STATE_SIZE_LEN;
147  static const u32 STATE_POS_LEN = BITS_BAR_COORD_LEN;
148  static const u32 STATE_SYMI_IDX = STATE_POS_IDX + STATE_POS_LEN;
149  static const u32 STATE_SYMI_LEN = BITS_SYMI;
150  static const u32 STATE_BITS = STATE_SYMI_IDX + STATE_SYMI_LEN;
151 
152  Element_DBar() : Element<CC>(MFM_UUID_FOR("DBar", DBAR_VERSION)) { }
153 
154  u32 GetSymI(const T &atom) const {
155  if (!IsOurType(atom.GetType()))
156  FAIL(ILLEGAL_STATE);
157  return atom.GetStateField(STATE_SYMI_IDX,STATE_SYMI_LEN);
158  }
159 
160  SPoint GetMax(const T &atom) const {
161  if (!IsOurType(atom.GetType()))
162  FAIL(ILLEGAL_STATE);
163  return MakeSigned(toUPoint<BITS_WIDE,BITS_HIGH>(atom.GetStateField(STATE_SIZE_IDX,STATE_SIZE_LEN)));
164  }
165 
166  SPoint GetPos(const T &atom) const {
167  if (!IsOurType(atom.GetType()))
168  FAIL(ILLEGAL_STATE);
169  return MakeSigned(toUPoint<BITS_WIDE,BITS_HIGH>(atom.GetStateField(STATE_POS_IDX,STATE_POS_LEN)));
170  }
171 
172  bool FitsInRep(const SPoint & v) const {
173  return v.BoundedBy(SPoint(0,0),SPoint((1<<BITS_WIDE)-1,(1<<BITS_HIGH)-1));
174  }
175 
176  void SetSize(T &atom, const SPoint & v) const {
177  if (!IsOurType(atom.GetType()))
178  FAIL(ILLEGAL_STATE);
179  if (!FitsInRep(v))
180  FAIL(ILLEGAL_ARGUMENT);
181  atom.SetStateField(STATE_SIZE_IDX,STATE_SIZE_LEN,toUTiny<BITS_WIDE,BITS_HIGH>(MakeUnsigned(v)));
182  }
183 
184  void SetPos(T &atom, const SPoint v) const {
185  if (!IsOurType(atom.GetType()))
186  FAIL(ILLEGAL_STATE);
187  if (!FitsInRep(v))
188  FAIL(ILLEGAL_ARGUMENT);
189  atom.SetStateField(STATE_POS_IDX,STATE_POS_LEN,toUTiny<BITS_WIDE,BITS_HIGH>(MakeUnsigned(v)));
190  }
191 
192  void SetSymI(T &atom, const u32 sym) const {
193  if (!IsOurType(atom.GetType()))
194  FAIL(ILLEGAL_STATE);
195  if (sym >= PSYM_SYMMETRY_COUNT)
196  FAIL(ILLEGAL_ARGUMENT);
197  atom.SetStateField(STATE_SYMI_IDX,STATE_SYMI_LEN, sym);
198  }
199 
200  virtual const T & GetDefaultAtom() const
201  {
202  static T defaultAtom(TYPE(),0,0,STATE_BITS);
203  return defaultAtom;
204  }
205 
206  T GetAtom(const SPoint & size, const SPoint & pos) const
207  {
208  T atom = GetDefaultAtom();
209  SetSize(atom,size);
210  SetPos(atom,pos);
211 
212  return atom;
213  }
214 
215  virtual u32 DefaultPhysicsColor() const
216  {
217  return 0xffffff00;
218  }
219 
220  virtual u32 DefaultLowlightColor() const
221  {
222  return 0xff7f7f00;
223  }
224 
225  virtual u32 PercentMovable(const T& you, const T& me, const SPoint& offset) const
226  {
227  return 0;
228  }
229 
230  virtual u32 LocalPhysicsColor(const T & atom, u32 selector) const
231  {
232  switch (selector) {
233  case 1: {
234  SPoint barMax = GetMax(atom);
235  SPoint myPos = GetPos(atom);
236  return ColorMap_SEQ6_PuRd::THE_INSTANCE.
237  GetInterpolatedColor(myPos.GetEuclideanLength(),
238  0,barMax.GetEuclideanLength(),
239  0xffff0000);
240  }
241  default:
242  return Element<CC>::PhysicsColor();
243  }
244  }
245 
249  virtual u32 Diffusability(EventWindow<CC> & ew, SPoint nowAt, SPoint maybeAt) const {
250  return this->NoDiffusability(ew, nowAt, maybeAt);
251  }
252 
253  virtual void Behavior(EventWindow<CC>& window) const
254  {
255  // Get self, sanity check
256  T self = window.GetCenterAtom();
257  const u32 selfType = self.GetType();
258  if (!IsOurType(selfType)) FAIL(ILLEGAL_STATE);
259 
260  // Establish our symmetry before non-self access through window
261  u32 symi = GetSymI(self);
262  window.SetSymmetry((PointSymmetry) symi);
263 
264  Random & random = window.GetRandom();
265 
266  SPoint barMax = GetMax(self);
267  SPoint myPos = GetPos(self);
268  // myPos.Print(stderr)
269 
270  const MDist<R> md = MDist<R>::get();
271 
272  SPoint anInconsistent;
273  u32 inconsistentCount = 0;
274  T unmakeGuy;
275 
276  u32 consistentCount = 0;
277 
278  SPoint toMake;
279  T makeGuy;
280  u32 makeCount = 0;
281 
282  SPoint toEat;
283  u32 eatCount = 0;
284 
285  // Scan event window outside self
286  for (u32 idx = md.GetFirstIndex(1); idx <= md.GetLastIndex(R); ++idx) {
287  const SPoint sp = md.GetPoint(idx);
288  const SPoint shearX(sp.GetY(),0);
289 
290  // First question: A 'bar grid' site?
291  bool onGrid = (sp.GetX()&1)==0 && (sp.GetY()&1)==0;
292 
293  if (onGrid) {
294  // Next question: Site within the bounds of the bar?
295 
296  const SPoint theirBarPos = sp+shearX+myPos;
297  bool inBar = theirBarPos.BoundedBy(SPoint(0,0),barMax);
298 
299  if (inBar) {
300  // Next question: Site empty?
301 
302  const T other = window.GetRelativeAtom(sp);
303  const u32 otherType = other.GetType();
304 
305  bool isEmpty = Element_Empty<CC>::THE_INSTANCE.IsType(otherType);
306 
307  if (isEmpty) {
308 
309  if (random.OneIn(++makeCount)) {
310  toMake = sp;
311  makeGuy = self; // Start with us
312  SetPos(makeGuy,theirBarPos); // Update position
313  //window.SetRelativeAtom(sp,them); // Store
314  }
315 
316  } else {
317 
318  // Next question: Are they also a bar?
319  if (IsOurType(otherType)) {
320 
321  // Next question: Are they consistent with us?
322 
323  SPoint otherBarMax = GetMax(other);
324  SPoint otherPos = GetPos(other);
325 
326  SPoint otherPosMapped = otherPos-sp-shearX;
327  if (otherBarMax==barMax && otherPosMapped == myPos) {
328  ++consistentCount;
329  } else if (random.OneIn(++inconsistentCount)) {
330  anInconsistent = sp;
331  // Inconsistent Bars decay to Res
333  }
334  }
335 
336  }
337  }
338  } else {
339  // This is a non-grid site. We'd kind of like it to be Res,
340  // and if not that, empty, but we'd really like it not to
341  // have Bar's in it
342 
343  const T other = window.GetRelativeAtom(sp);
344  const u32 otherType = other.GetType();
345 
346  bool isRes = otherType == Element_Res<CC>::TYPE();
347  if (isRes) {
348  ++consistentCount;
349  if (random.OneIn(++eatCount)) {
350  toEat = sp;
351  }
352  }
353  else {
354 
355  bool isEmpty = Element_Empty<CC>::THE_INSTANCE.IsType(otherType);
356 
357  if (isEmpty) ++consistentCount;
358  else {
359  bool iDBar = IsOurType(otherType);
360  if (iDBar) {
361  if (random.OneIn(++inconsistentCount)) {
362  anInconsistent = sp;
364  }
365  }
366  }
367  }
368  }
369  }
370 
371  // Scan finished. Let's decide what to do.
372 
373  // First question: Are we inconsistent with anybody?
374  if (inconsistentCount > 0) {
375  // Next question: Are we much more consistent than inconsistent?
376  if (consistentCount > 3*inconsistentCount) {
377  // Yes. Punish selected loser
378  window.SetRelativeAtom(anInconsistent, unmakeGuy);
379  } else if (inconsistentCount > 3*consistentCount) {
380  // If we're way inconsistent, let's res out and let them have us
382  }
383  } else {
384  // No inconsistencies. Do we have something to make, and eat?
385  if (makeCount > 0 && eatCount > 0) {
386  window.SetRelativeAtom(toMake, makeGuy);
388  }
389  else {
390  // Super-special case: Are we the max corner and all consistent?
391  if (myPos == barMax-SPoint(1,1)) {
392  // Is there an empty off end to us?
393  SPoint offset(0,2);
394  T offEnd = window.GetRelativeAtom(offset);
395  const u32 offType = offEnd.GetType();
396  if (Element_Empty<CC>::THE_INSTANCE.IsType(offType) && eatCount > 0) {
397  // T corner = self;
398  T corner = Element_SBar<CC>::THE_INSTANCE.GetAtom(barMax,SPoint(0,0));
399  u32 symi = GetSymI(self);
400  symi = (symi+6)%PSYM_SYMMETRY_COUNT;
401  // ++symi;
402  // if (symi > PSYM_DEG270L)
403  // symi = PSYM_DEG000L;
404  Element_SBar<CC>::THE_INSTANCE.SetSymI(corner,symi);
405  window.SetRelativeAtom(offset, corner);
407  }
408  }
409  }
410  }
411 
412  }
413 
414  };
415 
416  template <class CC>
417  Element_DBar<CC> Element_DBar<CC>::THE_INSTANCE;
418 
419 }
420 
421 #endif /* ELEMENT_DBAR_H */
virtual void Behavior(EventWindow< CC > &window) const
Definition: Element_DBar.h:253
u32 GetFirstIndex(const u32 radius) const
Definition: MDist.h:112
virtual u32 PercentMovable(const T &you, const T &me, const SPoint &offset) const
Definition: Element_DBar.h:225
u32 GetType() const
Definition: Element.h:290
Definition: Element_DBar.h:20
Definition: Element_Empty.h:41
Definition: Random.h:45
u32 GetLastIndex(const u32 radius) const
Definition: MDist.h:129
void SetSymmetry(const PointSymmetry psym)
Definition: EventWindow.h:110
void SetCenterAtom(const T &atom)
Definition: EventWindow.h:220
u32 NoDiffusability(EventWindow< CC > &ew, SPoint nowAt, SPoint maybeAt) const
Definition: Element.h:508
bool BoundedBy(const Point< T > &lowerBound, const Point< T > &upperBound) const
Definition: Point.tcc:223
virtual u32 DefaultLowlightColor() const
Definition: Element_DBar.h:220
Definition: Element_DBar.h:59
bool OneIn(u32 odds)
Definition: Random.h:96
T GetY() const
Definition: Point.tcc:40
Random & GetRandom()
Definition: EventWindow.h:122
const T & GetRelativeAtom(const SPoint &offset) const
Definition: EventWindow.tcc:26
virtual u32 Diffusability(EventWindow< CC > &ew, SPoint nowAt, SPoint maybeAt) const
Definition: Element_DBar.h:249
const T & GetCenterAtom() const
Definition: EventWindow.h:209
virtual const T & GetDefaultAtom() const
Definition: Element.h:382
virtual const T & GetDefaultAtom() const
Definition: Element_DBar.h:200
virtual u32 LocalPhysicsColor(const T &atom, u32 selector) const
Definition: Element_DBar.h:230
virtual u32 DefaultPhysicsColor() const
Definition: Element_DBar.h:215
Definition: MDist.h:69
bool IsType(u32 type) const
Definition: Element.h:345
static MDist< R > & get()
Definition: MDist.tcc:193
Definition: Element_Res.h:48
Definition: ElementTable.h:43
virtual u32 PhysicsColor() const
Definition: Element.h:398
double GetEuclideanLength() const
Definition: Point.tcc:58
bool SetRelativeAtom(const SPoint &offset, const T &atom)
Definition: EventWindow.tcc:15
Definition: Atom.h:43
T GetX() const
Definition: Point.tcc:34