Ejemplo n.º 1
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?

            // 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));
        }
Ejemplo n.º 2
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);
        }