private void move()
            {
                for (int i = specimens.Count - 1; i >= 0; i--)
                {
                    Specimen s = specimens[i];

                    if (s.age == consts.maxAge)
                    {
                        specimens.RemoveAt(i);
                        continue;
                    }

                    s.age++;

                    int ox, oy;

                    plyr.pd.Invoke(b.getView(s.pos.x, s.pos.y), s.g, rnd, out ox, out oy);

                    Board.Position npos;
                    SpecimenState  sstate = b.move(s.pos, ox, oy, out npos);
                    s.pos = npos;

                    if (sstate == SpecimenState.Win)
                    {
                        s.score++;
                        plyr.score++;
                        resetSpecimen(s);
                    }
                    else if (sstate == SpecimenState.Dead)
                    {
                        specimens.RemoveAt(i);
                    }
                }
            }
            // evaluate a move onto this position
            public SpecimenState move(Position ipos, int ox, int oy, out Position rpos)
            {
                if (ox > 1 || ox < -1 || oy > 1 || oy < -1)
                {
                    throw new Exception("Invalid move");
                }

                int x = ipos.x + ox;
                int y = ipos.y + oy;

                SpecimenState premss = boundsCheck(x, y);

                if (premss == SpecimenState.Dead)
                {
                    rpos = new Position(x, y);
                    return(SpecimenState.Dead);
                }

                rpos = grid[x, y].moveFrom(ipos);

                SpecimenState postmss = boundsCheck(rpos.x, rpos.y);

                if (postmss != SpecimenState.Alive)
                {
                    return(postmss);
                }

                if (grid[rpos.x, rpos.y].moveTo(rpos) == SpecimenState.Dead)
                {
                    return(SpecimenState.Dead);
                }

                return(SpecimenState.Alive);
            }
            private bool admissibleStartingCellCheck(Position sp)
            {
                int maxTurns = consts.maxAge;

                HashSet <Position> seen = new HashSet <Position>();               // only set things seen when we move onto them
                List <Position>    due  = new List <Position>();
                List <Position>    cur  = new List <Position>();

                cur.Add(sp);

                int turnCount = 0;

                while (cur.Count > 0 && turnCount < maxTurns)
                {
                    foreach (Position next in cur)
                    {
                        for (int i = -1; i <= 1; i++)
                        {
                            for (int j = -1; j <= 1; j++)
                            {
                                Position      np;
                                SpecimenState ss = this.move(next, i, j, out np);

                                if (ss == SpecimenState.Win)
                                {
                                    // glorious victory
                                    return(true);
                                }

                                if (ss == SpecimenState.Alive)
                                {
                                    if (!seen.Contains(np))
                                    {
                                        seen.Add(np);
                                        due.Add(np);
                                    }
                                }
                            }
                        }
                    }

                    var t = cur;
                    cur = due;
                    due = t;
                    due.Clear();

                    turnCount++;
                }

                return(false);
            }