using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Drawing;

namespace Sokoban {

     class Lada {

        private List<Point> _LadakHelye = new List<Point>();
        private List<int> _LadakLepesSzama = new List<int>();
        private Point _JatekosHelye = new Point();
        private int[] _Palya = new int[32];
        private Point _Cel = new Point();
        private string _Iranyok = "";
        private int _Szint = 0;
        private byte _X, _Y;
        
        public Lada(byte [,]Palya,byte x,byte y) {
            X = x; Y = y;
            setPalya(Palya);
        }

         public Lada(int[] Palya, Point JatekosHelye, List<Point> ladak, string iranyok) {
             _JatekosHelye.X = JatekosHelye.X; _JatekosHelye.Y = JatekosHelye.Y;
             _Iranyok = iranyok; Palya.CopyTo(_Palya, 0); setLadakHelye(ladak);
         }

        public int[] Palya {
            get { return _Palya; }
            set { _Palya = value; }
        }

        public byte X {
            get { return _X; }
            set { _X = value; }
        }

        public byte Y {
            get { return _Y; }
            set { _Y = value; }
        }

        public Point Cel {
            get { return _Cel; }
            set { _Cel = value; }
        }

         public Point JatekosHelye {
             get { return _JatekosHelye; }
             set { _JatekosHelye = value; }
         }

         public int Szint {
             get { return _Szint; }
             set { _Szint = value; }
         }

         public List<Point> LadakHelye{
             get { return _LadakHelye; }
             set { _LadakHelye=value; }
         }

         public string Iranyok {
             get { return _Iranyok; }
         }

         public void setLadakHelye(List<Point> helyek) {
             Point hely; 
             foreach (Point p in helyek) {
                 hely = new Point(); hely.X = p.X; hely.Y = p.Y;
                 _LadakHelye.Add(hely); 
             }
         }

         public void setPalya(byte[,] tom) {
             Point hely;

             for (byte i = 0; i < 32; ++i) {
                 for (byte j = 0; j < 32; ++j) {
                     if (_X > i && _Y > j) {
                         if (tom[i, j] != 0 && tom[i, j] != 4 && tom[i, j] != 1 && tom[i, j] != 5) _Palya[i] |= (1 << j);
                         if (tom[i, j] == 2 || tom[i, j] == 6) {
                             hely = new Point(); hely.X = i; hely.Y = j; _LadakHelye.Add(hely); _LadakLepesSzama.Add(0);
                         }
                         if (tom[i, j] == 1 || tom[i, j] == 5) { _JatekosHelye.X = i; _JatekosHelye.Y = j; }
                     }
                     else _Palya[i] |= (1 << j);
                 }
             }
         }
      
         
        public bool Fel(Point p, int i) {
            _Cel.X = p.X + 1; _Cel.Y = p.Y; Point ujHely = new Point();
            Jatekos j = new SzelessegiJatekos(this).Kereses();

            if (j != null) {
                _JatekosHelye.X = p.X; _JatekosHelye.Y = p.Y;
                _Palya[p.X] &= ~(1 << p.Y); _Palya[p.X - 1] |= (1 << p.Y);
                ujHely.X = p.X - 1; ujHely.Y = p.Y;
                _LadakHelye.Remove(_LadakHelye[i]); _LadakHelye.Insert(i, ujHely);
                _Szint += j.Szint + 1; _Iranyok = j.Iranyok + "8,";
                return true;
            }
            return false;
        }

         public bool Le(Point p, int i) {
            _Cel.X = p.X - 1 ; _Cel.Y = p.Y; Point ujHely = new Point();
            Jatekos j = new SzelessegiJatekos(this).Kereses();

            if (j != null){
                _JatekosHelye.X = p.X; _JatekosHelye.Y = p.Y;
                _Palya[p.X] &= ~(1 << p.Y); _Palya[p.X + 1] |= (1 << p.Y);
                ujHely.X = p.X + 1; ujHely.Y = p.Y;
                _LadakHelye.Remove(_LadakHelye[i]); _LadakHelye.Insert(i, ujHely);
                _Szint += j.Szint + 1; _Iranyok = j.Iranyok + "2,";
                return true;
            }
            return false;
        }

         public bool Jobbra(Point p, int i) {
            _Cel.X = p.X; _Cel.Y = p.Y - 1; Point ujHely = new Point();
            Jatekos j = new SzelessegiJatekos(this).Kereses();

            if (j != null){
                _JatekosHelye.X = p.X; _JatekosHelye.Y = p.Y;
                _Palya[p.X] &= ~(1 << p.Y); _Palya[p.X] |= (1 << p.Y + 1);
                 ujHely.X = p.X; ujHely.Y = p.Y + 1;
                _LadakHelye.Remove(_LadakHelye[i]); _LadakHelye.Insert(i, ujHely);
                _Szint += j.Szint + 1; _Iranyok = j.Iranyok + "6,";
                return true;
            }
            return false;
        }

         public bool Balra(Point p, int i) {
            _Cel.X = p.X; _Cel.Y = p.Y + 1; Point ujHely = new Point();
            Jatekos j = new SzelessegiJatekos(this).Kereses();

            if (j != null) {
                _JatekosHelye.X = p.X; _JatekosHelye.Y = p.Y;
                _Palya[p.X] &= ~(1 << p.Y); _Palya[p.X] |= (1 << p.Y - 1);
                ujHely.X = p.X; ujHely.Y = p.Y - 1;
                _LadakHelye.Remove(_LadakHelye[i]); _LadakHelye.Insert(i, ujHely);
                _Szint += j.Szint + 1; _Iranyok = j.Iranyok + "4,";
                return true;
            }
            return false;
        }

        public bool CeleE(Hashtable cel) {
            foreach (Point p in _LadakHelye) {
                if (!cel.ContainsKey(p)) return false;
            }
            return true;
        }
        
        public bool LehetE(Point p,int iranyX,int iranyY,Hashtable cel,int i) {

            Point hely = new Point();
            hely.X = p.X + iranyX; hely.Y = p.Y + iranyY;

            if(SzelessegiLada.Uzemmod)
                if(cel.ContainsKey(hely)) return false;

            //A célpozíció a táblán belül van e
            if (p.X + iranyX > 31 || p.Y + iranyY > 31
                || p.X + iranyX < 0 || p.Y + iranyY < 0) return false;

            //A láda elért e a játékossal
            if ((_Palya[p.X - iranyX] & (1 << (p.Y - iranyY))) != 0) return false;

            //Megmondja hogy a célmező üres e
            if ((_Palya[hely.X] & (1 << (hely.Y))) != 0) return false;
            
            //Deadlock figyelés
            if (!cel.ContainsKey(hely)) {
                if (iranyX != 0) {
                    if (((_Palya[p.X + (iranyX << 1)] & (1 << p.Y)) != 0) &&
                        ((_Palya[p.X + (iranyX << 1)] & (1 << (p.Y + 1))) != 0) &&
                        ((_Palya[p.X + iranyX] & (1 << (p.Y + 1))) != 0)) return false;
                    if (((_Palya[p.X + (iranyX << 1)] & (1 << p.Y)) != 0) &&
                        ((_Palya[p.X + (iranyX << 1)] & (1 << (p.Y - 1))) != 0) &&
                        ((_Palya[p.X + iranyX] & (1 << (p.Y - 1))) != 0)) return false;    
                }
                else {
                    if (((_Palya[p.X] & (1 << (p.Y + (iranyY << 1)))) != 0) &&
                        ((_Palya[p.X + 1] & (1 << (p.Y + (iranyY << 1)))) != 0) &&
                        ((_Palya[p.X + 1] & (1 << (p.Y + iranyY))) != 0)) return false;
                    if (((_Palya[p.X] & (1 << (p.Y + (iranyY << 1)))) != 0) &&
                        ((_Palya[p.X - 1] & (1 << (p.Y + (iranyY << 1)))) != 0) &&
                        ((_Palya[p.X - 1] & (1 << (p.Y + iranyY))) != 0)) return false;       
                }
            }

            return true;
        }
    }
}
