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