예제 #1
0
        private StateHash CalculateStateHash(MapTile pos1, MapTile pos2, MapTile pos3, MapTile pos4, MapTile[] positions, eMapSymmetry symmetry)
        {
            StateHash sh;

            sh.a = 0; sh.b = 0; sh.c = 0; sh.d = 0;

#if SYMMETRY_FOR_STATE_HASH_CHECK
            if (pos1 != null)
            {
                sh.Add(pos1.Index[(int)symmetry], 1);
            }
            if (pos2 != null)
            {
                sh.Add(pos2.Index[(int)symmetry], 1);
            }
            if (pos3 != null)
            {
                sh.Add(pos3.Index[(int)symmetry], 1);
            }
            if (pos4 != null)
            {
                sh.Add(pos4.Index[(int)symmetry], 1);
            }

            for (int idx = 0; idx < positions.Length; idx++)
            {
                if (positions[idx] != null)
                {
                    sh.Add(positions[idx].Index[(int)symmetry], 2);
                }
            }
#else
            if (pos1 != null)
            {
                sh.Add(pos1.Index, 1);
            }
            if (pos2 != null)
            {
                sh.Add(pos2.Index, 1);
            }
            if (pos3 != null)
            {
                sh.Add(pos3.Index, 1);
            }
            if (pos4 != null)
            {
                sh.Add(pos4.Index, 1);
            }

            for (int idx = 0; idx < positions.Length; idx++)
            {
                if (positions[idx] != null)
                {
                    sh.Add(positions[idx].Index, 2);
                }
            }
#endif

            return(sh);
        }
예제 #2
0
        private MapTile[,] tiles; // x,y indexing

        private bool LoadMapImpl(Tuple <MapTile.TileType, MovingObject.ObjectType>[,] map)
        {
            this.width  = map.GetLength(1);
            this.height = map.GetLength(0);

            tiles = new MapTile[width, height];

            ExitTile = null;

            int actorsCount = 0;

            int x = 0, y = 0;
            int index = 0;

            foreach (var t in map)
            {
                x = index % width;
                y = index / width;
                index++;

                MapTile.TileType        tileType   = t.Item1;
                MovingObject.ObjectType objectType = t.Item2;

                var tile = new MapTile(tileType, x, y, index, this);

                tiles[x, y] = tile;

                if (tileType == MapTile.TileType.Exit)
                {
                    if (ExitTile != null)
                    {
                        //Console.WriteLine( "Map exit already defined" );
                        return(false);
                    }
                    ExitTile = tile;
                }

                if (objectType != MovingObject.ObjectType.None)
                {
                    tile.obj = new MovingObject {
                        type = objectType
                    }
                }
                ;

                if (objectType == MovingObject.ObjectType.Actor)
                {
                    actors[actorsCount++] = tile;
                }
                else if (objectType == MovingObject.ObjectType.AntiActor)
                {
                    contrActors.Add(tile);
                }
            }

            if (index != width * height)
            {
                //Console.WriteLine( "Invalid map data" );
                return(false);
            }

            if (TestIsOn == false && actorsCount == 0)
            {
                //Console.WriteLine( "No actors on map" );
                return(false);
            }

            if (TestIsOn == false && ExitTile == null)
            {
                //Console.WriteLine( "No exit on map" );
                return(false);
            }

            SetupTileNeighbourhood();

            Symmetry = eMapSymmetry.None;

            FindSymmetry();

            var res = CalculateDistanceToExit();

            return(res);
        }
예제 #3
0
        /// <summary>
        /// Most game logic is implemented in this method.
        /// </summary>
        public GameState GetNewState(GameState currentState, Direction dir, Func <StateHash, bool> checkHash)
        {
            MapTile pos1 = null;
            MapTile pos2 = null;
            MapTile pos3 = null;
            MapTile pos4 = null;

            MapTile[] contractorNewPos = new MapTile[currentState.ContrActors.Length];
            currentState.ContrActors.CopyTo(contractorNewPos, 0);

            // TODO: Boxes pushed by Actors and Contractors?

            if (actor1.Push(dir) == false)
            {
                return(null);
            }
            if (actor2.Push(dir) == false)
            {
                return(null);
            }
            if (actor3.Push(dir) == false)
            {
                return(null);
            }
            if (actor4.Push(dir) == false)
            {
                return(null);
            }

            // Step 1: Just Actors are moving. All movements are simultaneous.
            if (currentState.pos1 != null && GetNewPos(currentState.pos1, dir, out pos1) == false)
            {
                return(null);
            }
            if (currentState.pos2 != null && GetNewPos(currentState.pos2, dir, out pos2) == false)
            {
                return(null);
            }
            if (currentState.pos3 != null && GetNewPos(currentState.pos3, dir, out pos3) == false)
            {
                return(null);
            }
            if (currentState.pos4 != null && GetNewPos(currentState.pos4, dir, out pos4) == false)
            {
                return(null);
            }

            // Check Actors colliding themselves.
            if (pos1 != null && (pos1 == pos2 || pos1 == pos3 || pos1 == pos4) ||
                pos2 != null && (pos2 == pos3 || pos2 == pos4) ||
                pos3 != null && pos3 == pos4)
            {
                return(null);
            }

            // Step 2: ContrActors are moving. All movements are simultaneous. Check for collision with Actors the same time.
            // Consider removing Contractors from the list instead of nullifying them
            for (int idx = 0; idx < contractorNewPos.Length; idx++)
            {
                MapTile pos = contractorNewPos[idx];
                if (contractorNewPos[idx] != null)
                {
                    // Check for collision with Actors before movement
                    if (pos1 != null && pos1 == pos || pos2 != null && pos2 == pos || pos3 != null && pos3 == pos || pos4 != null && pos4 == pos)
                    {
                        return(null);
                    }

                    GetNewPos(pos, (Direction)((int)dir ^ 2), out pos);

                    if (pos != null)
                    {
                        // Check for collision with Actors after movement
                        if (pos1 != null && pos1 == pos || pos2 != null && pos2 == pos || pos3 != null && pos3 == pos || pos4 != null && pos4 == pos)
                        {
                            return(null);
                        }

                        // Check for collision with other Contractors, remove collided
                        for (int idxInner = 0; idxInner < idx; idxInner++)
                        {
                            if (contractorNewPos[idxInner] == pos)
                            {
                                pos = null;
                                break;
                            }
                        }
                    }
                    contractorNewPos[idx] = pos;
                }
            }

            // Step 3: Actors are pushed by pushers. All movements are simultaneous.
            if (pos1 != null && GetNewPos(pos1, null, out pos1) == false)
            {
                return(null);
            }
            if (pos2 != null && GetNewPos(pos2, null, out pos2) == false)
            {
                return(null);
            }
            if (pos3 != null && GetNewPos(pos3, null, out pos3) == false)
            {
                return(null);
            }
            if (pos4 != null && GetNewPos(pos4, null, out pos4) == false)
            {
                return(null);
            }

            // Check Actors colliding themselves.
            if (pos1 != null && (pos1 == pos2 || pos1 == pos3 || pos1 == pos4) ||
                pos2 != null && (pos2 == pos3 || pos2 == pos4) ||
                pos3 != null && pos3 == pos4)
            {
                return(null);
            }

            // Step 3: Contractors and Boxes are pushed by pushers. All movements are simultaneous.
            for (int idx = 0; idx < contractorNewPos.Length; idx++)
            {
                MapTile pos = contractorNewPos[idx];
                if (pos != null)
                {
                    GetNewPos(pos, null, out pos);

                    if (pos != null)
                    {
                        // Check for collision with Actors after movement
                        if (pos1 != null && pos1 == pos || pos2 != null && pos2 == pos || pos3 != null && pos3 == pos || pos4 != null && pos4 == pos)
                        {
                            return(null);
                        }

                        // Check for collision with other Contractors, remove collided
                        for (int idxInner = 0; idxInner < idx; idxInner++)
                        {
                            if (contractorNewPos[idxInner] == pos)
                            {
                                pos = null;
                                break;
                            }
                        }
                    }
                    contractorNewPos[idx] = pos;
                }
            }

            // Check if we already have same state
            var hash = CalculateStateHash(pos1, pos2, pos3, pos4, contractorNewPos, eMapSymmetry.None);

            if (checkHash != null && checkHash(hash) == false)
            {
                return(null);
            }

#if SYMMETRY_FOR_STATE_HASH_CHECK
            for (eMapSymmetry s = eMapSymmetry.Horizontal; s <= eMapSymmetry.Both; s++)
            {
                if ((Symmetry & s) == s)
                {
                    var hashOther = CalculateStateHash(pos1, pos2, pos3, pos4, s);
                    if (checkHash(hashOther) == false)
                    {
                        return(null);
                    }
                }
            }
#endif
            return(new GameState(currentState, pos1, pos2, pos3, pos4, contractorNewPos, dir, hash));
        }
예제 #4
0
        public GameState(GameState prevState, MapTile pos1, MapTile pos2, MapTile pos3, MapTile pos4, MapTile[] contrActors, Direction moveDir, StateHash hash)
        {
            this.PrevState   = prevState;
            this.pos1        = pos1;
            this.pos2        = pos2;
            this.pos3        = pos3;
            this.pos4        = pos4;
            this.ContrActors = contrActors;
            this.moveDir     = moveDir;
            this.Hash        = hash;

            if (prevState != null)
            {
                turn = prevState.turn + 1;
            }
        }