MFMv2.0.10
Movable Feast Machine Simulator 2.0.10
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Element_MQBar.h
1 #ifndef ELEMENT_MQBAR_H /* -*- C++ -*- */
2 #define ELEMENT_MQBAR_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 "P3Atom.h"
12 #include "ColorMap.h"
13 
14 namespace MFM
15 {
16 
17  enum {
18  MQBAR_VERSION=4
19  };
20 
49  template <class CC>
50  class Element_MQBar : public Element<CC>
51  {
52  // Extract short names for parameter types
53  typedef typename CC::ATOM_TYPE T;
54  typedef typename CC::PARAM_CONFIG P;
55 
56  enum { R = P::EVENT_WINDOW_RADIUS };
57 
58  template <u32 TVBITS>
59  static u32 toMag(u32 value) {
60  const u32 MAX = (1<<TVBITS)-1;
61  if (value < 0) {
62  FAIL(ILLEGAL_ARGUMENT);
63  }
64  if (value > MAX)
65  value = MAX;
66  u32 val = value;
67  return val;
68  }
69 
70  template <u32 TVBITS>
71  static u32 fromMag(const u32 value) {
72  const u32 MASK = (1<<TVBITS)-1;
73  u32 val = value&MASK;
74  return val;
75  }
76 
77  template <u32 TXBITS, u32 TYBITS>
78  static u32 toUTiny(const UPoint & v) {
79  u32 x = toMag<TXBITS>(v.GetX());
80  u32 y = toMag<TYBITS>(v.GetY());
81  return (x<<TYBITS)|y;
82  }
83 
84  template <u32 TXBITS, u32 TYBITS>
85  static UPoint toUPoint(const u32 bits) {
86 
87  u32 x = fromMag<TXBITS>(bits>>TYBITS);
88  u32 y = fromMag<TYBITS>(bits);
89  return UPoint(x,y);
90  }
91 
92  public:
93 
94  static Element_MQBar THE_INSTANCE;
95  static const u32 TYPE() {
96  return THE_INSTANCE.GetType();
97  }
98 
99  static bool IsOurType(u32 type) {
100  return type==TYPE();
101  }
102 
103  static const u32 BITS_WIDE = 5;
104  static const u32 BITS_HIGH = 7;
105  static const u32 BITS_SYMI = 2;
106 
107  static const u32 BITS_TIMER = 4; // Slow down the timer
108  static const u32 MAX_TIMER_VALUE = 9; //(1<<BITS_TIMER)-1;
109 
110  static const u32 BITS_BAR_COORD_LEN = BITS_WIDE + BITS_HIGH;
111 
112  static const u32 STATE_BITS_START = P3Atom<P>::P3_STATE_BITS_POS;
113 
114  typedef AtomicParameterType<CC, VD::U32, BITS_WIDE, STATE_BITS_START> APBarWidth;
115  typedef AtomicParameterType<CC, VD::U32, BITS_HIGH, APBarWidth::END> APBarHeight;
116  typedef AtomicParameterType<CC, VD::U32, BITS_WIDE, APBarHeight::END> APXPos;
117  typedef AtomicParameterType<CC, VD::U32, BITS_HIGH, APXPos::END> APYPos;
118  typedef AtomicParameterType<CC, VD::U32, BITS_SYMI, APYPos::END> APSymI;
119  typedef AtomicParameterType<CC, VD::U32, BITS_TIMER,APSymI::END> APTimer;
120 
121  APBarWidth m_barWidth;
122  APBarHeight m_barHeight;
123  APXPos m_xPos;
124  APYPos m_yPos;
125  APSymI m_symI;
126  APTimer m_timer;
127 
128  static const u32 STATE_BITS_END = APTimer::END;
129  static const u32 STATE_BITS_COUNT = STATE_BITS_END - STATE_BITS_START + 1;
130 
131  Element_MQBar() :
132  Element<CC>(MFM_UUID_FOR("MQBar", MQBAR_VERSION)),
133  m_barWidth(this,"width","Bar Width","Bar width", 0, 15, _GetNOnes32(BITS_WIDE)/*, 1*/),
134  m_barHeight(this,"height","Bar Height","Bar height", 0, 3*15, _GetNOnes32(BITS_HIGH)/*, 1*/),
135  m_xPos(this,"xpos","X pos","X position within bar", 0, 0, _GetNOnes32(BITS_WIDE)/*, 1*/),
136  m_yPos(this,"ypos","Y pos","Y position within bar", 0, 0, _GetNOnes32(BITS_HIGH)/*, 1*/),
137  m_symI(this,"sym","Symmetry","Bar orientation, 0:N, 1:E, 2:S, 3:W", 0, 0, _GetNOnes32(BITS_SYMI)/*, 1*/),
138  m_timer(this,"timer","Timer","Cell maturity timer", 0, 0, _GetNOnes32(BITS_TIMER)/*, 1*/)
139  {
140  LOG.Message("%@ ctor %p", &this->GetUUID(), this);
141 
143  Element<CC>::SetName("MQBar");
144  }
145 
146  u32 GetSymI(const T &atom) const {
147  if (!IsOurType(atom.GetType()))
148  FAIL(ILLEGAL_STATE);
149  //return AFSymI::Read(this->GetBits(atom));
150  return m_symI.GetValue(atom);
151  }
152 
153  SPoint GetMax(const T &atom) const {
154  if (!IsOurType(atom.GetType()))
155  FAIL(ILLEGAL_STATE);
156  return SPoint(m_barWidth.GetValue(atom), m_barHeight.GetValue(atom));
157  }
158 
159  SPoint GetPos(const T &atom) const {
160  if (!IsOurType(atom.GetType()))
161  FAIL(ILLEGAL_STATE);
162  return SPoint(m_xPos.GetValue(atom), m_yPos.GetValue(atom));
163  }
164 
165  u32 GetTimer(const T &atom) const {
166  if (!IsOurType(atom.GetType()))
167  FAIL(ILLEGAL_STATE);
168  return m_timer.GetValue(atom);
169  }
170 
171  bool FitsInRep(const SPoint & v) const {
172  return v.BoundedBy(SPoint(0,0),SPoint(MakeMaskClip(BITS_WIDE),MakeMaskClip(BITS_HIGH)));
173  }
174 
175  void SetSize(T &atom, const SPoint & v) const {
176  if (!IsOurType(atom.GetType()))
177  FAIL(ILLEGAL_STATE);
178  if (!FitsInRep(v))
179  FAIL(ILLEGAL_ARGUMENT);
180  m_barWidth.SetValue(atom, v.GetX());
181  m_barHeight.SetValue(atom, v.GetY());
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  m_xPos.SetValue(atom, v.GetX());
190  m_yPos.SetValue(atom, v.GetY());
191  }
192 
193  void SetSymI(T &atom, const u32 sym) const {
194  if (!IsOurType(atom.GetType()))
195  FAIL(ILLEGAL_STATE);
196  if (sym >= PSYM_SYMMETRY_COUNT)
197  FAIL(ILLEGAL_ARGUMENT);
198  m_symI.SetValue(atom, sym);
199  }
200 
201  void SetTimer(T &atom, const u32 tmr) const {
202  if (!IsOurType(atom.GetType()))
203  FAIL(ILLEGAL_STATE);
204  if (tmr > MAX_TIMER_VALUE)
205  FAIL(ILLEGAL_ARGUMENT);
206  m_timer.SetValue(atom, tmr);
207  }
208 
209  virtual const T & GetDefaultAtom() const
210  {
211  static T defaultAtom(TYPE(), 0, 0, STATE_BITS_COUNT);
212  const SPoint QBAR_SIZE(15, 3 * 15);
213  SetSize(defaultAtom, QBAR_SIZE);
214  SetPos(defaultAtom, SPoint(0,0));
215  SetSymI(defaultAtom, 0);
216  return defaultAtom;
217  }
218 
219  virtual T BuildDefaultAtom() const
220  {
221  T atom = GetDefaultAtom();
222  return atom;
223  }
224 
225  virtual u32 DefaultPhysicsColor() const
226  {
227  return 0xffffff00;
228  }
229 
230  virtual u32 DefaultLowlightColor() const
231  {
232  return 0xff7f7f00;
233  }
234 
235  virtual u32 PercentMovable(const T& you, const T& me, const SPoint& offset) const
236  {
237  return 0;
238  }
239 
240 
241  virtual u32 LocalPhysicsColor(const T & atom, u32 selector) const
242  {
243  switch (selector) {
244  case 1: {
245  SPoint barMax = GetMax(atom);
246  SPoint myPos = GetPos(atom);
247  return ColorMap_SEQ6_PuRd::THE_INSTANCE.
248  GetInterpolatedColor(myPos.GetEuclideanLength(),
249  0,barMax.GetEuclideanLength(),
250  0xffff0000);
251  }
252  default:
253  {
254  u32 timer = GetTimer(atom);
255  return ColorMap_SEQ6_GnBu::THE_INSTANCE.
256  GetInterpolatedColor(timer,0,MAX_TIMER_VALUE - 1, Element<CC>::PhysicsColor());
257  }
258  }
259  return 0x0;
260  }
261 
265  virtual u32 Diffusability(EventWindow<CC> & ew, SPoint nowAt, SPoint maybeAt) const {
266  return this->NoDiffusability(ew, nowAt, maybeAt);
267  }
268 
269  virtual void Behavior(EventWindow<CC>& window) const
270  {
271  // Get self, sanity check
272  T self = window.GetCenterAtom();
273  const u32 selfType = self.GetType();
274  if (!IsOurType(selfType)) FAIL(ILLEGAL_STATE);
275 
276  u32 ourTimer = this->GetTimer(self);
277 
278  // Establish our symmetry before non-self access through window
279  u32 symi = this->GetSymI(self);
280  window.SetSymmetry((PointSymmetry) symi);
281 
282  Random & random = window.GetRandom();
283 
284  SPoint barMax = this->GetMax(self);
285  SPoint myPos = this->GetPos(self);
286 
287  const MDist<R> & md = MDist<R>::get();
288 
289  SPoint anInconsistent;
290  u32 inconsistentCount = 0;
291  T unmakeGuy;
292 
293  u32 consistentCount = 0;
294 
295  SPoint toMake;
296  T makeGuy;
297  u32 makeCount = 0;
298 
299  SPoint toEat;
300  u32 eatCount = 0;
301 
302  bool neighborTimer = false;
303  u32 minTimer = 0;
304  u32 maxTimer = 0;
305 
306  // Scan event window outside self
307  for (u32 idx = md.GetFirstIndex(1); idx <= md.GetLastIndex(R); ++idx) {
308  const SPoint sp = md.GetPoint(idx);
309 
310  // First question: A 'bar grid' site?
311  bool onGrid = (sp.GetX()&1)==0 && (sp.GetY()&1)==0;
312 
313  // Second question: Inside _our_ bar?
314  const SPoint theirBarPos = sp+myPos;
315  bool inBar = theirBarPos.BoundedBy(SPoint(0,0),barMax);
316 
317  if (onGrid) {
318  // Next question: Site within the bounds of the bar?
319 
320  if (inBar) {
321  // Next question: Site empty?
322 
323  const T other = window.GetRelativeAtom(sp);
324  const u32 otherType = other.GetType();
325 
326  bool isEmpty = Element_Empty<CC>::THE_INSTANCE.IsType(otherType);
327 
328  if (isEmpty) {
329 
330  if (random.OneIn(++makeCount)) {
331  toMake = sp;
332  makeGuy = self; // Start with us
333  SetPos(makeGuy,theirBarPos); // Update position
334  SetTimer(makeGuy, 0); // They are young
335  }
336 
337  } else {
338 
339  // Next question: Are they also a bar?
340  if (IsOurType(otherType)) {
341 
342  // Next question: Are they consistent with us?
343 
344  SPoint otherBarMax = GetMax(other);
345  SPoint otherPos = GetPos(other);
346 
347  SPoint otherPosMapped = otherPos-sp;
348  u32 otherTimer = GetTimer(other);
349 
350  if (otherBarMax==barMax && otherPosMapped == myPos) {
351  ++consistentCount;
352 
353  // They are consistent. Inspect their timer
354  if (!neighborTimer || otherTimer < minTimer)
355  minTimer = otherTimer;
356  if (!neighborTimer || otherTimer > maxTimer)
357  maxTimer = otherTimer;
358  neighborTimer = true;
359 
360  } else {
361  u32 otherTimer = GetTimer(other);
362 
363  // An inconsistent guy younger than us decays
364  if (otherTimer < ourTimer && random.OneIn(++inconsistentCount)) {
365  anInconsistent = sp;
366  // Inconsistent Bars decay to Res
368  }
369  }
370  }
371 
372  }
373  }
374  } else {
375  // This is a non-grid site. If it's in our bar, We'd kind
376  // of like it to be Res, and if not that, empty, but we'd
377  // really like it not to have Bar's in it
378 
379  if (inBar) {
380  const T other = window.GetRelativeAtom(sp);
381  const u32 otherType = other.GetType();
382 
383  bool isRes = otherType == Element_Res<CC>::TYPE();
384  if (isRes) {
385  ++consistentCount;
386  if (random.OneIn(++eatCount)) {
387  toEat = sp;
388  }
389  }
390  else {
391 
392  bool isEmpty = Element_Empty<CC>::THE_INSTANCE.IsType(otherType);
393 
394  if (isEmpty) ++consistentCount;
395  else {
396  bool iQBar = IsOurType(otherType);
397  if (iQBar) {
398  u32 iQBarTimer = GetTimer(other);
399  if (iQBarTimer < ourTimer && random.OneIn(++inconsistentCount)) {
400  anInconsistent = sp;
402  }
403  }
404  }
405  }
406  }
407  }
408  }
409 
410  // Scan finished. Let's decide what to do.
411 
412  // First question: Are we inconsistent with anybody?
413  if (inconsistentCount > 0) {
414 
415  // Next question: Are we much more consistent than inconsistent?
416  if (consistentCount > 3 * inconsistentCount) {
417 
418  // Yes. Punish selected loser
419  window.SetRelativeAtom(anInconsistent, unmakeGuy);
420 
421  } else if (inconsistentCount > 3 * consistentCount) {
422 
423  // If we're way inconsistent, let's res out and let them have us
425 
426  } else {
427 
428 #if 0
429  // We're neither way consistent nor way inconsistent. We
430  // will survive but dock our timer
431  u32 ourTimer = GetTimer(self);
432  if (ourTimer > 0) {
433  if (neighborTimer && minTimer < ourTimer)
434  ourTimer = minTimer;
435  else
436  --ourTimer;
437  SetTimer(self,ourTimer);
438  window.SetCenterAtom(self);
439  }
440 #endif
441  }
442  } else {
443  // No inconsistencies. Do we have something to make, and eat?
444  if (makeCount > 0 && eatCount > 0) {
445  window.SetRelativeAtom(toMake, makeGuy);
447  }
448  else {
449  // Super-special case: Are we the max corner and all consistent?
450  if (myPos == barMax-SPoint(1,1)) {
451  // Is there an empty off end to us?
452  SPoint offset(0,2);
453  T offEnd = window.GetRelativeAtom(offset);
454  const u32 offType = offEnd.GetType();
455  if (Element_Empty<CC>::THE_INSTANCE.IsType(offType) && eatCount > 0) {
456  T corner = self;
457  u32 symi = GetSymI(self);
458  ++symi;
459  if (symi > PSYM_DEG270L)
460  symi = PSYM_DEG000L;
461  SetSymI(corner,symi);
462  SetPos(corner,SPoint(0,0));
463  SetTimer(corner,0);
464  window.SetRelativeAtom(offset, corner);
466  }
467  }
468  {
469  // We are alllll good, with nothing to do. What is our timer situation?
470  u32 ourTimer = GetTimer(self);
471  if (ourTimer < MAX_TIMER_VALUE && (ourTimer==0 || (neighborTimer && minTimer+1 >= ourTimer))) {
472  if (random.OneIn(ourTimer+1)) {
473  ++ourTimer;
474  SetTimer(self,ourTimer);
475  window.SetCenterAtom(self);
476  }
477  }
478  }
479  }
480  }
481 
482  }
483 
484  };
485 
486  template <class CC>
487  Element_MQBar<CC> Element_MQBar<CC>::THE_INSTANCE;
488 
489 }
490 
491 #endif /* ELEMENT_MQBAR_H */
u32 GetFirstIndex(const u32 radius) const
Definition: MDist.h:112
virtual u32 DefaultLowlightColor() const
Definition: Element_MQBar.h:230
virtual const T & GetDefaultAtom() const
Definition: Element_MQBar.h:209
u32 GetType() const
Definition: Element.h:290
virtual u32 DefaultPhysicsColor() const
Definition: Element_MQBar.h:225
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
void SetName(const char *name)
Definition: Element.h:209
void SetAtomicSymbol(const char *symbol)
Definition: Element.h:193
bool BoundedBy(const Point< T > &lowerBound, const Point< T > &upperBound) const
Definition: Point.tcc:223
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
const T & GetCenterAtom() const
Definition: EventWindow.h:209
const UUID & GetUUID() const
Definition: Element.h:355
virtual const T & GetDefaultAtom() const
Definition: Element.h:382
Definition: MDist.h:69
bool IsType(u32 type) const
Definition: Element.h:345
virtual u32 LocalPhysicsColor(const T &atom, u32 selector) const
Definition: Element_MQBar.h:241
Element(const UUID &uuid)
Definition: Element.h:246
static MDist< R > & get()
Definition: MDist.tcc:193
virtual T BuildDefaultAtom() const
Definition: Element_MQBar.h:219
virtual u32 Diffusability(EventWindow< CC > &ew, SPoint nowAt, SPoint maybeAt) const
Definition: Element_MQBar.h:265
Definition: Element_Res.h:48
Definition: ElementTable.h:43
double GetEuclideanLength() const
Definition: Point.tcc:58
void Message(const char *format,...)
Definition: Logger.h:287
bool SetRelativeAtom(const SPoint &offset, const T &atom)
Definition: EventWindow.tcc:15
Definition: Atom.h:43
virtual u32 PercentMovable(const T &you, const T &me, const SPoint &offset) const
Definition: Element_MQBar.h:235
virtual void Behavior(EventWindow< CC > &window) const
Definition: Element_MQBar.h:269
T GetX() const
Definition: Point.tcc:34