HOG2
Fling.cpp
Go to the documentation of this file.
1 /*
2  * Fling.cpp
3  * hog2
4  *
5  * Created by Nathan Sturtevant on 3/5/10.
6  * Copyright 2010 NS Software. All rights reserved.
7  *
8  */
9 
10 #include "Fling.h"
11 #include <stdint.h>
12 #include <string.h>
13 #include <algorithm>
14 
15 void FlingBoard::SetPiece(int which)
16 {
17  uint64_t val = (1ull<<which);
18  board |= val;
19 }
20 
21 void FlingBoard::ClearPiece(int which)
22 {
23  uint64_t val = (1ull<<which);
24  board &= (~val);
25 }
26 
27 void FlingBoard::SetHole(int which)
28 {
29  uint64_t val = (1ull<<which);
30  holes |= val;
31 }
32 
33 void FlingBoard::ClearHole(int which)
34 {
35  uint64_t val = (1ull<<which);
36  holes &= (~val);
37 }
38 
39 void FlingBoard::SetObstacle(int which)
40 {
41  uint64_t val = (1ull<<which);
42  obstacles |= val;
43 }
44 
46 {
47  uint64_t val = (1ull<<which);
48  obstacles &= (~val);
49 }
50 
51 bool FlingBoard::HasPiece(int offset) const
52 {
53  uint64_t val = (1ull<<offset);
54  return (board & val);
55 }
56 
57 bool FlingBoard::HasPiece(int x, int y) const
58 {
59  uint64_t val = (1ull<<(y*width+x));
60  return (board & val);
61 }
62 
63 bool FlingBoard::HasHole(int offset) const
64 {
65  uint64_t val = (1ull<<offset);
66  return (holes & val);
67 }
68 
69 bool FlingBoard::HasHole(int x, int y) const
70 {
71  uint64_t val = (1ull<<(y*width+x));
72  return (holes & val);
73 }
74 
75 bool FlingBoard::HasObstacle(int offset) const
76 {
77  uint64_t val = (1ull<<offset);
78  return (obstacles & val);
79 }
80 
81 bool FlingBoard::HasObstacle(int x, int y) const
82 {
83  uint64_t val = (1ull<<(y*width+x));
84  return (obstacles & val);
85 }
86 
87 void FlingBoard::AddFling(unsigned int x, unsigned int y)
88 {
89  assert(x < width);
90  assert(y < height);
91  //if (board[y*width+x] == false)
92  if (HasPiece(y*width+x) == false)
93  {
94  SetPiece(y*width+x);
95  //board[y*width+x] = true;
96  locs.push_back({y*width+x, currId++});
97 
98  std::sort(locs.begin(), locs.end(), std::greater<std::pair<int,int>>());
99  }
100 }
101 
102 void FlingBoard::AddFling(unsigned int offset)
103 {
104  assert(offset < width*height);
105  //assert(offset < board.size());
106  assert(HasPiece(offset) == false);
107  //assert(board[offset] == false);
108  SetPiece(offset);
109  //board[offset] = true;
110  locs.push_back({offset, currId++});
111  std::sort(locs.begin(), locs.end(), std::greater<std::pair<int,int>>());
112 }
113 
114 void FlingBoard::RemoveFling(unsigned int x, unsigned int y)
115 {
116  assert(x < width);
117  assert(y < height);
118  RemoveFling(y*width+x);
119 }
120 
121 void FlingBoard::RemoveFling(unsigned int offset)
122 {
123  ClearPiece(offset);
124  //board[offset] = false;
125  for (unsigned int x = 0; x < width*height; x++)
126  {
127  if (locs[x].first == offset)
128  {
129  // TODO: just use erase here
130  locs[x] = locs.back();
131  locs.pop_back();
132  std::sort(locs.begin(), locs.end(), std::greater<std::pair<int,int>>());
133  return;
134  }
135  }
136 }
137 
138 bool FlingBoard::CanMove(int which, int x, int y) const
139 {
140  int xx = which%width;
141  int yy = which/width;
142 
143  xx+=x; yy += y;
144 
145  bool first = true;
146  while ((xx >= 0) && (xx < width) && (yy >= 0) && (yy < height))
147  {
148  //if (board[yy*width+xx])
149  if (HasPiece(yy*width+xx) || (HasObstacle(yy*width+xx)))
150  return !first;
151  if (HasHole(yy*width+xx))
152  return false;
153  first = false;
154  xx+=x; yy += y;
155  }
156  return false;
157 
158 }
159 
160 int FlingBoard::GetIndexInLocs(int offset) const
161 {
162  // could do a binary search; TODO: profile to see if necessary
163  for (size_t i = 0; i < locs.size(); i++)
164  {
165  if (locs[i].first == offset)
166  {
167  return i;
168  }
169  }
170  assert(!"Didn't find index of location!");
171  return -1;
172 }
173 
174 int FlingBoard::GetIndexInLocs(int x, int y) const
175 {
176  return GetIndexInLocs(y*width+x);
177 }
178 
179 void FlingBoard::Move(int which, int x, int y)
180 {
181  int xx = which%width;
182  int yy = which/width;
183 
184  int index = GetIndexInLocs(xx, yy);
185 
186  int lastx = xx;
187  int lasty = yy;
188  xx+=x; yy += y;
189  while ((xx >= 0) && (xx < width) && (yy >= 0) && (yy < height))
190  {
191  //board[lasty*width+lastx] = board[yy*width+xx];
192  if (HasPiece(yy*width+xx))
193  {
194  SetPiece(lasty*width+lastx);
195  locs[index].first = lasty*width+lastx;
196  index = GetIndexInLocs(xx, yy);
197  }
198  else if (HasObstacle(yy*width+xx))
199  {
200  SetPiece(lasty*width+lastx);
201  locs[index].first = lasty*width+lastx;
202  // no piece can be on the obstacle, so we
203  // let that location be cleared
204  std::sort(locs.begin(), locs.end(), std::greater<std::pair<int,int>>());
205 // locs.resize(0);
206 // for (int t = width*height-1; t >= 0; t--)
207 // if (HasPiece(t))//[t])
208 // locs.push_back(t);
209  return;
210  }
211  else {
212  ClearPiece(lasty*width+lastx);
213  }
214  lastx = xx;
215  lasty = yy;
216  xx+=x; yy += y;
217  }
218  ClearPiece(lasty*width+lastx);
219  locs.erase(locs.begin()+index);
220  std::sort(locs.begin(), locs.end(), std::greater<std::pair<int,int>>());
221  //board[lasty*width+lastx] = false;
222 // locs.resize(0);
223 // for (int t = width*height-1; t >= 0; t--)
224 // if (HasPiece(t))//[t])
225 // locs.push_back(t);
226 }
227 
229 {
230  int xx = m.startLoc%width;
231  int yy = m.startLoc/width;
232  int x, y;
233 
234  switch (m.dir)
235  {
236  case kRight: x = 1; y = 0; break;
237  case kLeft: x = -1; y = 0; break;
238  case kUp: x = 0; y = -1; break;
239  case kDown: x = 0; y = 1; break;
240  }
241 
242  int lastx = xx;
243  int lasty = yy;
244  xx+=x; yy += y;
245  while ((xx >= 0) && (xx < width) && (yy >= 0) && (yy < height))
246  {
247  //board[lasty*width+lastx] = board[yy*width+xx];
248  if (HasPiece(yy*width+xx) || HasObstacle(yy*width+xx))
249  {
250  return lasty*width+lastx;
251  }
252  lastx = xx;
253  lasty = yy;
254  xx+=x; yy += y;
255  }
256  assert(!"No collision found for piece");
257  return -1;
258 }
259 
260 
261 void GetMirror(const FlingBoard &in, FlingBoard &out, bool h, bool v)
262 {
263  out = in;
264  out.Reset();
265  for (size_t x = 0; x < in.width; x++)
266  {
267  for (size_t y = 0; y < in.height; y++)
268  {
269  if (in.HasPiece(x, y))
270  {
271  int newx = x;
272  int newy = y;
273  if (h)
274  newx = in.width-x-1;
275  if (v)
276  newy = in.height-y-1;
277  out.AddFling(newx, newy);
278  }
279  }
280  }
281 }
282 
284 {
285  bool done = false;
286  while (1)
287  {
288  // find piece
289  for (size_t x = 0; x < in.width; x++)
290  {
291  if (in.HasPiece(x, 0))
292  {
293  done = true;
294  break;
295  }
296  }
297 
298  if (done) break;
299  // move over
300  for (size_t y = 1; y < in.height; y++)
301  {
302  for (size_t x = 0; x < in.width; x++)
303  {
304  if (in.HasPiece(x, y))
305  {
306  in.AddFling(x, y-1);
307  in.RemoveFling(x, y);
308  }
309  }
310  }
311  }
312  while (1)
313  {
314  for (size_t y = 0; y < in.height; y++)
315  {
316  if (in.HasPiece(0, y))
317  {
318  return;
319  }
320  }
321 
322  for (size_t x = 1; x < in.width; x++)
323  {
324  for (size_t y = 0; y < in.height; y++)
325  {
326  if (in.HasPiece(x, y))
327  {
328  in.AddFling(x-1, y);
329  in.RemoveFling(x, y);
330  }
331  }
332  }
333  }
334 
335 }
336 
337 uint64_t GetCanonicalHash(uint64_t which)
338 {
339  Fling f;
340  FlingBoard b;
341  f.GetStateFromHash(which, b);
342  ShiftToCorner(b);
343  which = f.GetStateHash(b);
344 
345  FlingBoard flip;
346  GetMirror(b, flip, true, true);
347  ShiftToCorner(flip);
348 
349  if (f.GetStateHash(flip) < which)
350  which = f.GetStateHash(flip);
351 
352  GetMirror(b, flip, true, false);
353  ShiftToCorner(flip);
354  if (f.GetStateHash(flip) < which)
355  which = f.GetStateHash(flip);
356 
357  GetMirror(b, flip, false, true);
358  ShiftToCorner(flip);
359  if (f.GetStateHash(flip) < which)
360  which = f.GetStateHash(flip);
361 
362  return which;
363 }
364 
366 {
367  specificGoalLoc = false;
368  specificGoalPanda = false;
369  initBinomial();
370  // initBinomialSums();
371 }
372 
373 void Fling::SetGoalPanda(int which)
374 {
375  specificGoalPanda = true;
376  goalLoc = which;
377 }
378 
380 {
381  specificGoalPanda = false;
382 }
383 
384 void Fling::SetGoalLoc(int val)
385 {
386  specificGoalLoc = true;
387  goalLoc = val;
388 }
389 
391 {
392  specificGoalLoc = false;
393 }
394 
395 bool Fling::GoalTest(const FlingBoard &node, const FlingBoard &goal) const
396 {
397  if (specificGoalLoc)
398  return (node.locs.size() == 1 && node.locs[0].first == goalLoc);
399  if (specificGoalPanda)
400  {
401  return (node.locs.size() == 1 && node.locs[0].second == goalLoc);
402  }
403  return (node.locs.size() == 1);
404 }
405 
406 
407 void Fling::GetSuccessors(const FlingBoard &nodeID, std::vector<FlingBoard> &neighbors) const
408 {
409  neighbors.resize(0);
410  for (unsigned int x = 0; x < nodeID.locs.size(); x++)
411  {
412  if (nodeID.CanMove(nodeID.locs[x].first, 1, 0))
413  {
414  FlingBoard b(nodeID);
415  b.Move(nodeID.locs[x].first, 1, 0);
416  neighbors.push_back(b);
417  }
418  if (nodeID.CanMove(nodeID.locs[x].first, -1, 0))
419  {
420  FlingBoard b(nodeID);
421  b.Move(nodeID.locs[x].first, -1, 0);
422  neighbors.push_back(b);
423  }
424  if (nodeID.CanMove(nodeID.locs[x].first, 0, 1))
425  {
426  FlingBoard b(nodeID);
427  b.Move(nodeID.locs[x].first, 0, 1);
428  neighbors.push_back(b);
429  }
430  if (nodeID.CanMove(nodeID.locs[x].first, 0, -1))
431  {
432  FlingBoard b(nodeID);
433  b.Move(nodeID.locs[x].first, 0, -1);
434  neighbors.push_back(b);
435  }
436  }
437 }
438 
439 void Fling::GetActions(const FlingBoard &nodeID, std::vector<FlingMove> &actions) const
440 {
441  actions.resize(0);
442  FlingMove m;
443  for (size_t x = 0; x < nodeID.locs.size(); x++)
444  {
445  if (nodeID.CanMove(nodeID.locs[x].first, 1, 0))
446  {
447  m.startLoc = nodeID.locs[x].first;
448  m.dir = kRight;
449  actions.push_back(m);
450  }
451  if (nodeID.CanMove(nodeID.locs[x].first, -1, 0))
452  {
453  m.startLoc = nodeID.locs[x].first;
454  m.dir = kLeft;
455  actions.push_back(m);
456  }
457  if (nodeID.CanMove(nodeID.locs[x].first, 0, 1))
458  {
459  m.startLoc = nodeID.locs[x].first;
460  m.dir = kDown;
461  actions.push_back(m);
462  }
463  if (nodeID.CanMove(nodeID.locs[x].first, 0, -1))
464  {
465  m.startLoc = nodeID.locs[x].first;
466  m.dir = kUp;
467  actions.push_back(m);
468  }
469  }
470 }
471 
473 {
474  if (!s.HasPiece(a.startLoc))
475  return false;
476  switch (a.dir)
477  {
478  case kRight: return s.CanMove(a.startLoc, 1, 0); break;
479  case kLeft: return s.CanMove(a.startLoc, -1, 0); break;
480  case kDown: return s.CanMove(a.startLoc, 0, 1); break;
481  case kUp: return s.CanMove(a.startLoc, 0, -1); break;
482  }
483  return false;
484 }
485 
487 {
488  switch (a.dir)
489  {
490  case kRight: s.Move(a.startLoc, 1, 0); break;
491  case kLeft: s.Move(a.startLoc, -1, 0); break;
492  case kDown: s.Move(a.startLoc, 0, 1); break;
493  case kUp: s.Move(a.startLoc, 0, -1); break;
494  }
495 }
496 
498 {
499  assert(false);
500 }
501 
503 {
504  t = f;
505  ApplyAction(t, a);
506 }
507 
508 FlingMove Fling::GetAction(const FlingBoard &s1, const FlingBoard &s2) const
509 {
510  std::vector<FlingMove> m1;
511  GetActions(s1, m1);
512  FlingMove between = {0, kUp};
513  FlingBoard tmp;
514  bool found = false;
515  for (int x = 0; x < m1.size(); x++)
516  {
517  GetNextState(s1, m1[x], tmp);
518  if (tmp == s2)
519  {
520  found = true;
521  between = m1[x];
522  break;
523  }
524  }
525  assert(found == true);
526  return between;
527 }
528 
529 
530 uint64_t Fling::GetStateHash(const FlingBoard &node) const
531 {
532  uint64_t hash = 0;
533  bool onBoard = false;
534  for (unsigned int x = 0; x < node.locs.size(); x++)
535  {
536  hash |= (1ull<<node.locs[x].first);
537  if (node.locs[x].second == goalLoc)
538  onBoard = true;
539 // std::cout << "Storing piece at " << node.locs[x] << std::endl;
540 // printf("0x%llX (out:%d)\n", hash, x);
541  }
542  if (specificGoalPanda && onBoard)
543  hash |= (1ull<<63);
544  // printf("0x%llX (out)\n", hash);
545  return hash;
546 // return 0;
547 }
548 
549 void Fling::GetStateFromHash(uint64_t parent, FlingBoard &s) const
550 {
551 // printf("0x%llX (in)\n", parent);
552  s.Reset();
553  for (int x = 0; x < s.width*s.height; x++)
554  {
555  if (1 == ((parent>>x)&0x1))
556  {
557 // std::cout << "Setting piece at " << x << std::endl;
558  s.AddFling(x);
559  }
560  }
561 }
562 
563 uint64_t Fling::GetActionHash(FlingMove act) const
564 {
565  return 0;
566 }
567 
568 void Fling::OpenGLDraw(const FlingBoard&b) const
569 {
570  double radius = 1.0/(1+max(b.width, b.height));
571  double diameter = radius*2;
572  double xLoc = -1+radius;
573  double yLoc = -1+radius;
574 
575  glColor3f(0.0, 0.0, 0.5); //
576  glBegin(GL_QUADS);
577  glVertex3f(-1+diameter, -1+diameter, 0);
578  glVertex3f(-1+diameter, -1+(diameter*b.height)+diameter, 0);
579  glVertex3f(-1+diameter*(b.width)+diameter, -1+diameter*(b.height)+diameter, 0);
580  glVertex3f(-1+diameter*(b.width)+diameter, -1+diameter, 0);
581  glEnd();
582 
583  glLineWidth(2.0);
584  glColor3f(1.0, 1.0, 1.0); // white
585  glBegin(GL_LINES);
586  for (double x = 0; x <= b.width; x++)
587  {
588  glVertex3f(-1+(x+1)*diameter, -1+diameter, 0);
589  glVertex3f(-1+(x+1)*diameter, -1+diameter*b.height+diameter, -0.01);
590  xLoc += diameter;
591  }
592  for (double y = 0; y <= b.height; y++)
593  {
594  yLoc += diameter;
595  glVertex3f(-1+diameter, -1+(y+1)*diameter, 0);
596  glVertex3f(-1+diameter*b.width+diameter, -1+(y+1)*diameter, -0.01);
597  }
598  glEnd();
599  glLineWidth(1.0);
600 
601  xLoc = -1+radius;
602  for (double x = 0; x < b.width; x++)
603  {
604  xLoc += diameter;
605  yLoc = -1+radius;
606  for (double y = 0; y < b.height; y++)
607  {
608  yLoc += diameter;
609  if (b.HasPiece(x, y))
610  {
611  rgbColor r = Colors::GetColor(b.locs[b.GetIndexInLocs(x, y)].second, 0, b.currId, 9); // 4
612  glColor3f(r.r, r.g, r.b);
613  DrawSphere(xLoc, yLoc, 0, radius*0.8);
614  }
615  else if (b.HasHole(x, y))
616  {
617  glColor3f(0, 0, 0);
618  DrawBox(xLoc, yLoc, 0, radius);
619  }
620  else if (b.HasObstacle(x, y))
621  {
622  glColor3f(1, 1, 1);
623  DrawBox(xLoc, yLoc, 0, radius);
624  }
625  }
626  }
627 }
628 
630 {
631  double radius = 1.0/(1+max(b.width, b.height));
632  double diameter = radius*2;
633  double xLoc;
634  double yLoc;
635  double r = radius*0.85;
636 
637  glColor3f(1.0, 1.0, 1.0); //
638  glBegin(GL_QUADS);
639  glVertex3f(-2, -2, 0);
640  glVertex3f(-2, +2, 0);
641  glVertex3f(+2, +2, 0);
642  glVertex3f(+2, -2, 0);
643  glEnd();
644 
645 // glLineWidth(2.0);
646 // glColor3f(1.0, 1.0, 1.0); // white
647 // glBegin(GL_LINES);
648 // for (double x = 0; x <= b.width; x++)
649 // {
650 // glVertex3f(-1+(x+1)*diameter, -1+diameter, 0);
651 // glVertex3f(-1+(x+1)*diameter, -1+diameter*b.height+diameter, -0.01);
652 // xLoc += diameter;
653 // }
654 // for (double y = 0; y <= b.height; y++)
655 // {
656 // yLoc += diameter;
657 // glVertex3f(-1+diameter, -1+(y+1)*diameter, 0);
658 // glVertex3f(-1+diameter*b.width+diameter, -1+(y+1)*diameter, -0.01);
659 // }
660 // glEnd();
661  glLineWidth(1.0);
662 
663  xLoc = -1+radius;
664  glDisable(GL_LIGHTING);
665  glLineWidth(8.0);
666  glColor4f(0.0, 0.0, 0.0, 1.0); // ffd700
667  // glColor4f(0.0, 1.0, 0.0, 0.5); // ffd700
668  for (double x = 0; x < b.width; x++)
669  {
670  xLoc += diameter;
671  yLoc = -1+radius;
672  for (double y = 0; y < b.height; y++)
673  {
674  yLoc += diameter;
675  //rgbColor r = GetColor(x+y*b.width, 0, b.width*b.height, 4);
676 
677  if (b.HasPiece(x, y))
678  {
679  glBegin(GL_QUADS);
680  glVertex3f(xLoc-r, yLoc-r-r, -0.02);
681  glVertex3f(xLoc-r, yLoc+r-r, -0.02);
682  glVertex3f(xLoc+r, yLoc+r-r, -0.02);
683  glVertex3f(xLoc+r, yLoc-r-r, -0.02);
684  glEnd();
685  }
686  //DrawSphere(xLoc, yLoc, 0, radius);
687  }
688  }
689  glLineWidth(1.0);
690  glEnable(GL_LIGHTING);
691 }
692 
693 
695 {
696  double radius = 1.0/(1+max(b.width, b.height));
697  double diameter = radius*2;
698  double xLoc = -1+radius;
699  double yLoc;
700  double r = radius*0.80;
701 
702  glDisable(GL_LIGHTING);
703  glLineWidth(8.0);
704  glColor4f(0.0, 0.5, 0.0, 1.0); // ffd700
705 // glColor4f(0.0, 1.0, 0.0, 0.5); // ffd700
706  for (double x = 0; x < b.width; x++)
707  {
708  xLoc += diameter;
709  yLoc = -1+radius;
710  for (double y = 0; y < b.height; y++)
711  {
712  yLoc += diameter;
713  //rgbColor r = GetColor(x+y*b.width, 0, b.width*b.height, 4);
714 
715  if (b.HasPiece(x, y))
716  {
717  glBegin(GL_QUADS);
718  glVertex3f(xLoc-r, yLoc-r, -0.02);
719  glVertex3f(xLoc-r, yLoc+r, -0.02);
720  glVertex3f(xLoc+r, yLoc+r, -0.02);
721  glVertex3f(xLoc+r, yLoc-r, -0.02);
722  glEnd();
723  }
724  //DrawSphere(xLoc, yLoc, 0, radius);
725  }
726  }
727  glLineWidth(1.0);
728  glEnable(GL_LIGHTING);
729 }
730 
731 
732 void Fling::OpenGLDraw(const FlingBoard&b, const FlingMove &m) const
733 {
734  double radius = 1.0/(1+max(b.width, b.height));
735  double diameter = radius*2;
736  double xLoc = -1+radius+diameter;
737  double yLoc = -1+radius+diameter;
738 
739  glColor3f(1.0, 1.0, 1.0);
740  glLineWidth(10);
741  glBegin(GL_TRIANGLES);
742 
743 // int x = b.locs[m.startLoc]%b.width;
744 // int y = b.locs[m.startLoc]/b.width;
745  int x = m.startLoc%b.width;
746  int y = m.startLoc/b.width;
747  switch (m.dir)
748  {
749  case kLeft:
750  glVertex3f(xLoc+x*diameter, yLoc+y*diameter-radius/2, -radius);
751  glVertex3f(xLoc+x*diameter, yLoc+y*diameter+radius/2, -radius);
752  glVertex3f(xLoc+x*diameter-radius, yLoc+y*diameter, -radius);
753  break;
754  case kRight:
755  glVertex3f(xLoc+x*diameter, yLoc+y*diameter+radius/2, -radius);
756  glVertex3f(xLoc+x*diameter, yLoc+y*diameter-radius/2, -radius);
757  glVertex3f(xLoc+x*diameter+radius, yLoc+y*diameter, -radius);
758  break;
759  case kUp:
760  glVertex3f(xLoc+x*diameter+radius/2, yLoc+y*diameter, -radius);
761  glVertex3f(xLoc+x*diameter-radius/2, yLoc+y*diameter, -radius);
762  glVertex3f(xLoc+x*diameter, yLoc+y*diameter-radius, -radius);
763  break;
764  case kDown:
765  glVertex3f(xLoc+x*diameter-radius/2, yLoc+y*diameter, -radius);
766  glVertex3f(xLoc+x*diameter+radius/2, yLoc+y*diameter, -radius);
767  glVertex3f(xLoc+x*diameter, yLoc+y*diameter+radius, -radius);
768  break;
769  }
770  glEnd();
771  glLineWidth(1.0);
772 }
773 
774 bool Fling::GetXYFromPoint(const FlingBoard &b, point3d loc, int &x, int &y) const
775 {
776  double radius = 1.0/(1+max(b.width, b.height));
777  double diameter = radius*2;
778 
779  loc.x = loc.x-diameter+1;
780  loc.y = loc.y-diameter+1;
781  loc.x /= diameter;
782  loc.y /= diameter;
783  x = loc.x;
784  y = loc.y;
785 
786  if (x >= 0 && x < b.width && y >= 0 && y < b.height)
787  return true;
788  return false;
789 }
790 
791 void Fling::GLLabelState(const FlingBoard&b, const char *text) const
792 {
793  glDisable(GL_LIGHTING);
794  glEnable(GL_LINE_SMOOTH);
795  glDisable(GL_DEPTH_TEST);
796  glLineWidth(3.0);
797 
798  double radius = 1.0/(1+max(b.width, b.height));
799  double diameter = radius*2;
800  double xLoc = -1+radius;
801  double yLoc;
802 
803  for (double x = 0; x < b.width; x++)
804  {
805  xLoc += diameter;
806  yLoc = -1+radius;
807  for (double y = 0; y < b.height; y++)
808  {
809  yLoc += diameter;
810  glColor3f(1.0, 1.0, 1.0);
811  if (b.HasPiece(x, y))
812  {
813  const char *p;
814 
815  glPushMatrix();
816  glTranslatef(xLoc-radius+1/152.38, yLoc-radius+8/152.38, 0);
817  glScalef(.05/152.38, -.05/152.38, .05/152.38);
818  glTranslatef(0, 0, -2*radius);
819 
820  //glScalef(0.09f, -0.08f, 1.0);
821  //glTranslatef(0, 0, -2*radius);
822  for (p = text; *p; p++)
823  {
824  //printf("%c", *p);
825  //glutStrokeCharacter(GLUT_STROKE_ROMAN, *p);
826  }
827  glPopMatrix();
828  //printf("\n");
829  // draw text
830 // const char *c;
832 // glScalef(0.09f, -0.08f, 1.0);
834 // for (c=text; *c != '\0'; c++)
835 // {
836 // glutStrokeCharacter(GLUT_STROKE_ROMAN , *c);
837 // }
839  }
840  }
841  }
842 
843  glEnable(GL_DEPTH_TEST);
844  glEnable(GL_LIGHTING);
845  glDisable(GL_LINE_SMOOTH);
846  glLineWidth(1.0);
847 
848 }
849 
851 {
852  IncrementRank(b, 0);
853 }
854 
855 int Fling::IncrementRank(FlingBoard &b, int piece) const
856 {
857  int currPieceLocation = b.GetPieceLocation(piece);
858  int newPieceLocation;
859  // piece reached end of board
860  if (currPieceLocation == b.height*b.width-1-piece)
861  {
862  newPieceLocation = IncrementRank(b, piece+1)+1;
863  }
864  else {
865  newPieceLocation = currPieceLocation+1;
866  }
867  b.ClearPiece(currPieceLocation);
868  b.SetPiece(newPieceLocation);
869  b.locs[piece].first = newPieceLocation;
870  return newPieceLocation;
871 }
872 
873 
875 {
876  return binomial(spots, numPieces);
877 }
878 
880 {
881  return binomial(spots-(numPieces-2), 2);
882 }
883 
884 int64_t Fling::getMaxSinglePlayerRank2(int spots, int numPieces, int64_t firstIndex)
885 {
886  int NUM_SPOTS = spots;
887  int NUM_PIECES = numPieces;
888  unsigned int ls = 2;
889  int i = 0;
890  for (; ls > 0; ++i)
891  {
892  int64_t value;
893  if (ls > 0)
894  {
895  value = binomial(NUM_SPOTS-(NUM_PIECES-2) - i - 1, ls - 1);
896  }
897  else {
898  value = 0;
899  }
900  if (firstIndex < value)
901  {
902  ls--;
903  }
904  else {
905  firstIndex -= value;
906  }
907  }
908  return binomial(NUM_SPOTS-i,NUM_PIECES-2);
909 }
910 
912 {
913  int NUM_SPOTS = s.width*s.height;
914  int NUM_PIECES = (int)s.locs.size();
915 
916  int64_t r2 = 0;
917  int last = NUM_SPOTS-1;
918  for (int x = 0; x < NUM_PIECES; x++)
919  {
920  int64_t tmp = binomialSum(last, NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1, NUM_PIECES-1-x);
921  r2 += tmp;
922  last = NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1-1;
923  }
924  return r2;
925 }
926 
927 void Fling::rankPlayer(FlingBoard &s, int64_t &index1, int64_t &index2)
928 {
929  int NUM_SPOTS = s.width*s.height;
930  int NUM_PIECES = (int)s.locs.size();
931  index1 = 0;
932  int tot = NUM_SPOTS-1-(NUM_PIECES-2);
933  int last = tot;
934  for (int x = 0; x < 2; x++)
935  {
936  int64_t tmp = binomialSum(last, tot-s.locs[NUM_PIECES-1-x].first, (2)-1-x);
937  index1 += tmp;
938  last = tot-s.locs[NUM_PIECES-1-x].first-1;
939  }
940 
941  index2 = 0;
942  last = NUM_SPOTS-s.locs[NUM_PIECES-1-1].first-1-1;
943  for (int x = 2; x < NUM_PIECES; x++)
944  {
945  int64_t tmp = binomialSum(last, NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1, NUM_PIECES-1-x);
946  index2 += tmp;
947  last = NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1-1;
948  }
949 }
950 
951 void Fling::rankPlayerFirstTwo(FlingBoard &s, int64_t &index1)
952 {
953  int NUM_SPOTS = s.width*s.height;
954  int NUM_PIECES = (int)s.locs.size();
955 
956  index1 = 0;
957  int tot = NUM_SPOTS-1-(NUM_PIECES-2);
958  int last = tot;
959  for (int x = 0; x < 2; x++)
960  {
961  int64_t tmp = binomialSum(last, tot-s.locs[NUM_PIECES-1-x].first, (2)-1-x);
962  index1 += tmp;
963  last = tot-s.locs[NUM_PIECES-1-x].first-1;
964  }
965 }
966 
967 void Fling::rankPlayerRemaining(FlingBoard &s, int64_t &index2)
968 {
969  int NUM_SPOTS = s.width*s.height;
970  int NUM_PIECES = (int)s.locs.size();
971 
972  int last;
973  index2 = 0;
974  last = NUM_SPOTS-s.locs[NUM_PIECES-1-1].first-1-1;
975  for (int x = 2; x < NUM_PIECES; x++)
976  {
977  int64_t tmp = binomialSum(last, NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1, NUM_PIECES-1-x);
978  index2 += tmp;
979  last = NUM_SPOTS-s.locs[NUM_PIECES-1-x].first-1-1;
980  }
981 }
982 
983 
984 // returns true if it is a valid unranking given existing pieces
985 bool Fling::unrankPlayer(int64_t theRank, int pieces, FlingBoard &s)
986 {
987  int NUM_SPOTS = s.width*s.height;
988  int NUM_PIECES = pieces;
989 
990 // int tag = who + 1;
991  unsigned int ls = NUM_PIECES;
992 // memset(s.board, 0, NUM_SPOTS*sizeof(int));
993  s.Reset();
994  s.locs.resize(pieces);
995  for (int i=0; ls > 0; ++i)
996  {
997  int64_t value;
998  if (ls > 0)
999  {
1000  value = binomial(NUM_SPOTS - i - 1, ls - 1);
1001  }
1002  else {
1003  value = 0;
1004  }
1005  if (theRank < value)
1006  {
1007  s.SetPiece(i);
1008  //s.board[i] = true;
1009  s.locs[ls-1].first = i;
1010  s.locs[ls-1].second = ls-1;
1011  ls--;
1012  }
1013  else {
1014  s.ClearPiece(i);
1015  //s.board[i] = 0;
1016  theRank -= value;
1017  }
1018  }
1019  for (int x = 1; x < NUM_PIECES; x++)
1020  assert(s.locs[x-1] > s.locs[x]);
1021  return true;
1022 }
1023 
1024 //
1025 //
1026 //void Fling::initBinomialSums()
1027 //{
1028 // if (theSums.size() == 0)
1029 // {
1030 // theSums.resize((NUM_PIECES+1)*(NUM_SPOTS+1));
1031 // // sums.resize(NUM_PIECES+1);
1032 // for (int x = 0; x <= NUM_PIECES; x++)
1033 // {
1034 // // sums[x].resize(NUM_SPOTS+1);
1035 // int64_t result = 0;
1036 // for (int y = 0; y <= NUM_SPOTS; y++)
1037 // {
1038 // result+=binomial(y, x);
1039 // // sums[x][y] = result;
1040 // theSums[x*(NUM_SPOTS+1)+y] = result;
1041 // }
1042 // }
1043 // }
1044 //}
1045 //
1046 int64_t Fling::binomialSum(unsigned int n1, unsigned int n2, unsigned int k)
1047 {
1048  // static std::vector<std::vector<int64_t> > sums;
1049  //assert(theSums[k*(NUM_SPOTS+1)+n1]-theSums[k*(NUM_SPOTS+1)+n2] == sums[k][n1]-sums[k][n2]);
1050  int64_t result = 0;
1051  for (int x = n1; x > n2; x--)
1052  result += binomial(x, k);
1053  return result;
1054  //return theSums[k*(NUM_SPOTS+1)+n1]-theSums[k*(NUM_SPOTS+1)+n2];
1055  //return sums[k][n1]-sums[k][n2];
1056 }
1057 
1058 const int maxPieces = 14;
1059 
1061 {
1062  if (binomials.size() == 0)
1063  {
1064  for (int x = 0; x <= 56; x++)
1065  {
1066  for (int y = 0; y <= maxPieces; y++)
1067  {
1068  binomials.push_back(bi(x, y));
1069  }
1070  }
1071  }
1072 }
1073 
1074 int64_t Fling::binomial(unsigned int n, unsigned int k)
1075 {
1076  //assert(bi(n, k) == binomials[n*(1+NUM_PLAYERS*NUM_PIECES)+k]);
1077  return binomials[n*(1+maxPieces)+k];
1078 }
1079 
1080 int64_t Fling::bi(unsigned int n, unsigned int k)
1081 {
1082  int64_t num = 1;
1083  const unsigned int bound = (n - k);
1084  while(n > bound)
1085  {
1086  num *= n--;
1087  }
1088 
1089  int64_t den = 1;
1090  while(k > 1)
1091  {
1092  den *= k--;
1093  }
1094  return num / den;
1095 }
FlingBoard::HasHole
bool HasHole(int x, int y) const
Definition: Fling.cpp:69
FlingBoard::Move
void Move(int which, int x, int y)
Definition: Fling.cpp:179
loc::x
int x
Definition: MapGenerators.cpp:296
Colors::GetColor
rgbColor GetColor(float v, float vmin, float vmax, int type)
Given min/max values, get a color from a color schema.
Definition: Colors.cpp:24
Fling::GetXYFromPoint
bool GetXYFromPoint(const FlingBoard &b, point3d loc, int &x, int &y) const
Definition: Fling.cpp:774
rgbColor::b
float b
Definition: Colors.h:71
rgbColor
A color; r/g/b are between 0...1.
Definition: Colors.h:17
Fling::ClearGoalPanda
void ClearGoalPanda()
Definition: Fling.cpp:379
GetMirror
void GetMirror(const FlingBoard &in, FlingBoard &out, bool h, bool v)
Definition: Fling.cpp:261
Fling::UndoAction
virtual void UndoAction(FlingBoard &s, FlingMove a) const
Definition: Fling.cpp:497
Fling::binomials
std::vector< int64_t > binomials
Definition: Fling.h:202
Fling::OpenGLDraw
virtual void OpenGLDraw() const
Definition: Fling.h:187
numPieces
const int numPieces
Definition: Hexagon.h:38
loc::y
int y
Definition: MapGenerators.cpp:296
FlingBoard::obstacles
uint64_t obstacles
Definition: Fling.h:63
FlingBoard::GetIndexInLocs
int GetIndexInLocs(int x, int y) const
Definition: Fling.cpp:174
Fling::getMaxSinglePlayerRank2
int64_t getMaxSinglePlayerRank2(int spots, int numPieces)
Definition: Fling.cpp:879
Fling
Definition: Fling.h:137
DrawSphere
void DrawSphere(GLdouble _x, GLdouble _y, GLdouble _z, GLdouble tRadius)
Definition: GLUtil.cpp:433
FlingBoard::SetObstacle
void SetObstacle(int which)
Definition: Fling.cpp:39
FlingBoard::SetHole
void SetHole(int which)
Definition: Fling.cpp:27
Fling::goalLoc
int goalLoc
Definition: Fling.h:200
Fling::ApplyAction
virtual void ApplyAction(FlingBoard &s, FlingMove a) const
Definition: Fling.cpp:486
FlingBoard::ClearHole
void ClearHole(int which)
Definition: Fling.cpp:33
FlingBoard::height
unsigned int height
Definition: Fling.h:44
rgbColor::g
float g
Definition: Colors.h:71
FlingBoard::width
unsigned int width
Definition: Fling.h:43
pieces
const int pieces
Definition: RubiksCube7Edges.h:17
Fling::GetActionHash
virtual uint64_t GetActionHash(FlingMove act) const
Definition: Fling.cpp:563
FlingBoard::LocationAfterAction
int LocationAfterAction(FlingMove m)
Definition: Fling.cpp:228
Fling::binomial
int64_t binomial(unsigned int n, unsigned int k)
Definition: Fling.cpp:1074
kLeft
@ kLeft
Definition: Fling.h:74
FlingBoard::Reset
void Reset()
Definition: Fling.h:20
Fling::GetStateHash
virtual uint64_t GetStateHash(const FlingBoard &node) const
Definition: Fling.cpp:530
Fling::IncrementRank
void IncrementRank(FlingBoard &b) const
Definition: Fling.cpp:850
loc
Definition: MapGenerators.cpp:296
Fling::Fling
Fling()
Definition: Fling.cpp:365
kUp
@ kUp
Definition: Fling.h:74
kDown
@ kDown
Definition: Fling.h:74
point3d
#define point3d
Definition: GLUtil.h:123
FlingBoard::SetPiece
void SetPiece(int which)
Definition: Fling.cpp:15
FlingBoard::CanMove
bool CanMove(int which, int x, int y) const
Definition: Fling.cpp:138
FlingBoard::holes
uint64_t holes
Definition: Fling.h:64
Fling::SetGoalLoc
void SetGoalLoc(int val)
Definition: Fling.cpp:384
Fling::getMaxSinglePlayerRank
int64_t getMaxSinglePlayerRank(int spots, int numPieces)
Definition: Fling.cpp:874
FlingMove::startLoc
uint8_t startLoc
Definition: Fling.h:80
Fling::unrankPlayer
bool unrankPlayer(int64_t theRank, int pieces, FlingBoard &s)
Definition: Fling.cpp:985
Fling::GetAction
virtual FlingMove GetAction(const FlingBoard &s1, const FlingBoard &s2) const
Definition: Fling.cpp:508
Fling::OpenGLDrawPlain
virtual void OpenGLDrawPlain(const FlingBoard &b) const
Definition: Fling.cpp:629
Fling::GoalTest
virtual bool GoalTest(const FlingBoard &node, const FlingBoard &goal) const
Definition: Fling.cpp:395
Fling::rankPlayer
int64_t rankPlayer(FlingBoard &s)
Definition: Fling.cpp:911
FlingBoard::HasPiece
bool HasPiece(int x, int y) const
Definition: Fling.cpp:57
max
#define max(a, b)
Definition: MinimalSectorAbstraction.cpp:40
FlingBoard::AddFling
void AddFling(unsigned int x, unsigned int y)
Definition: Fling.cpp:87
Fling.h
rgbColor::r
float r
Definition: Colors.h:71
Fling::SetGoalPanda
void SetGoalPanda(int which)
Definition: Fling.cpp:373
Fling::specificGoalPanda
bool specificGoalPanda
Definition: Fling.h:199
DrawBox
void DrawBox(GLfloat xx, GLfloat yy, GLfloat zz, GLfloat rad)
Definition: GLUtil.cpp:285
Fling::GLLabelState
virtual void GLLabelState(const FlingBoard &, const char *) const
Definition: Fling.cpp:791
Fling::binomialSum
int64_t binomialSum(unsigned int n1, unsigned int n2, unsigned int k)
Definition: Fling.cpp:1046
Fling::LegalMove
bool LegalMove(const FlingBoard &, FlingMove)
Definition: Fling.cpp:472
Fling::GetSuccessors
virtual void GetSuccessors(const FlingBoard &nodeID, std::vector< FlingBoard > &neighbors) const
Definition: Fling.cpp:407
Fling::specificGoalLoc
bool specificGoalLoc
Definition: Fling.h:198
Fling::GetStateFromHash
virtual void GetStateFromHash(uint64_t parent, FlingBoard &s) const
Definition: Fling.cpp:549
FlingBoard::GetPieceLocation
int GetPieceLocation(int which) const
Definition: Fling.h:34
FlingMove::dir
tFlingDir dir
Definition: Fling.h:81
FlingBoard::locs
std::vector< std::pair< int, int > > locs
Definition: Fling.h:46
ShiftToCorner
void ShiftToCorner(FlingBoard &in)
Definition: Fling.cpp:283
FlingBoard::HasObstacle
bool HasObstacle(int x, int y) const
Definition: Fling.cpp:81
Fling::rankPlayerFirstTwo
void rankPlayerFirstTwo(FlingBoard &s, int64_t &index1)
Definition: Fling.cpp:951
FlingBoard::RemoveFling
void RemoveFling(unsigned int x, unsigned int y)
Definition: Fling.cpp:114
maxPieces
const int maxPieces
Definition: Fling.cpp:1058
Fling::GetNextState
virtual void GetNextState(const FlingBoard &, FlingMove, FlingBoard &) const
Definition: Fling.cpp:502
Fling::rankPlayerRemaining
void rankPlayerRemaining(FlingBoard &s, int64_t &index2)
Definition: Fling.cpp:967
Fling::GetActions
virtual void GetActions(const FlingBoard &nodeID, std::vector< FlingMove > &actions) const
Definition: Fling.cpp:439
Fling::OpenGLDrawAlternate
virtual void OpenGLDrawAlternate(const FlingBoard &) const
Definition: Fling.cpp:694
GetCanonicalHash
uint64_t GetCanonicalHash(uint64_t which)
Definition: Fling.cpp:337
FlingBoard::ClearPiece
void ClearPiece(int which)
Definition: Fling.cpp:21
FlingBoard::board
uint64_t board
Definition: Fling.h:62
FlingBoard::ClearObstacle
void ClearObstacle(int which)
Definition: Fling.cpp:45
Fling::bi
int64_t bi(unsigned int n, unsigned int k)
Definition: Fling.cpp:1080
FlingMove
Definition: Fling.h:77
FlingBoard
Definition: Fling.h:15
Fling::ClearGoalLoc
void ClearGoalLoc()
Definition: Fling.cpp:390
node
Nodes to be stored within a Graph.
Definition: Graph.h:170
FlingBoard::currId
int currId
Definition: Fling.h:60
Fling::initBinomial
void initBinomial()
Definition: Fling.cpp:1060
kRight
@ kRight
Definition: Fling.h:74