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

namespace Sokoban {

    class SzelessegiLada {
        
        private Hashtable Allapotok = new Hashtable();
        private List<Lada> NyiltLada = new List<Lada>();
        private List<Lada> ZartLada = new List<Lada>();
        private Hashtable  _CelMezok = new Hashtable();
        private static bool _Uzemmod;

        public SzelessegiLada() {
            byte[,] palya ={
               {3,3,3,3,3,3,3,3,3},
               {3,0,1,3,4,3,3,4,3},
               {3,0,0,3,0,3,3,0,3},
               {3,0,2,0,0,0,2,0,3},
               {3,0,0,3,2,3,0,0,3},
               {3,3,0,3,0,3,3,3,3},
               {3,3,0,0,0,0,0,4,3},
               {3,3,3,3,0,3,3,3,3},
               {3,3,3,3,3,3,3,3,3}
           };

           NyiltLada.Add(new Lada(palya, 9, 9));
           setCel(palya, 9, 9); _Uzemmod = true; volte(NyiltLada[0]);
        }

        public SzelessegiLada(byte[,] palya, byte x, byte y) {
            NyiltLada.Add(new Lada(palya, x, y));
            setCel(palya, x, y); _Uzemmod = true; volte(NyiltLada[0]);
        }

        public SzelessegiLada(Lada l,Hashtable cel,Point vizsgaltLada) {
            _CelMezok = cel; _Uzemmod = false; l.LadakHelye = new List<Point>();
            l.LadakHelye.Add(vizsgaltLada); NyiltLada.Add(l);
            volte(l);
        }

        public static bool Uzemmod{
            get { return _Uzemmod; }
        }

        public void setCel(byte[, ] tom, int x,int y) {
            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] == 6 || tom[i, j] == 4 || tom[i, j] == 5){
                            hely = new Point(); hely.X = i; hely.Y = j;
                            _CelMezok[hely] = "";
                        }
                    }
                }
            }
        }

        public Lada Kereses() {
            Lada l1,l2;

            if (NyiltLada[0].CeleE(_CelMezok)) return NyiltLada[0];
            while(NyiltLada.Count>0)
            {
                l1 = NyiltLada[0];
                l2 = KiterjesztLada(l1);
                if (l2 != null) return l2;
                NyiltLada.Remove(l1); ZartLada.Add(l1);
            }

            return null;
        }

        public Lada KiterjesztLada(Lada l) {
            List<Point> ladak = l.LadakHelye;
            SzelessegiLada kereso;
            int szint = l.Szint;
            Point hely=new Point(); Lada uj;
            int ig = ladak.Count;

            for (int i = 0; i < ig; ++i) {
                if (_Uzemmod) {
                    Hashtable cel;
                    foreach (DictionaryEntry de in _CelMezok) {
                        if ((l.Palya[((Point)de.Key).X] & (1 << ((Point)de.Key).Y)) == 0) {
                            cel = new Hashtable();
                            cel[de.Key] = ""; 
                            kereso = new SzelessegiLada(l, cel, ladak[i]);
                            uj = kereso.Kereses();
                            l.LadakHelye = ladak;
                            _Uzemmod = true;
                            if (uj != null) {
                                hely = uj.LadakHelye[0]; uj.LadakHelye = new List<Point>();
                                uj.setLadakHelye(ladak); uj.LadakHelye[i] = hely; 
                                if (uj.CeleE(_CelMezok)) 
                                    return uj;
                                if (!volte(uj)) NyiltLada.Insert (1, uj);
                            }
                        }
                    }
                    hely = ladak[i];
                }
                else hely = ladak[i];
                
                if (l.LehetE(hely,-1,0,_CelMezok,i)) {
                    uj = new Lada(l.Palya, l.JatekosHelye, ladak, l.Iranyok); uj.Szint = szint; 
                    if (uj.Fel(hely, i) && !volte(uj)) {
                        if (uj.CeleE(_CelMezok)) return uj; NyiltLada.Add(uj); 
                    }
                }
                if (l.LehetE(hely, 1, 0,_CelMezok,i)) {
                    uj = new Lada(l.Palya, l.JatekosHelye, ladak, l.Iranyok); uj.Szint = szint; 
                    if (uj.Le(hely, i) && !volte(uj)) {
                        if (uj.CeleE(_CelMezok)) return uj; NyiltLada.Add(uj);
                    } 
                }
                if (l.LehetE(hely, 0, 1,_CelMezok,i)) {
                    uj = new Lada(l.Palya, l.JatekosHelye, ladak, l.Iranyok); uj.Szint = szint; 
                    if (uj.Jobbra(hely, i) && !volte(uj)) {
                        if (uj.CeleE(_CelMezok)) return uj; NyiltLada.Add(uj);
                    }
                }
                if (l.LehetE(hely, 0, -1,_CelMezok,i)) {
                    uj = new Lada(l.Palya, l.JatekosHelye, ladak, l.Iranyok); uj.Szint = szint; 
                    if (uj.Balra(hely, i) && !volte(uj)) {
                        if (uj.CeleE(_CelMezok)) return uj; NyiltLada.Add(uj); 
                    }
                }
            }
            return null;
        }

        public bool volte(Lada l) {
            bool volt;
      
            if (!Allapotok.ContainsKey(l.JatekosHelye)) {
                Allapotok[l.JatekosHelye] = new List<Hashtable>();
            }
            else {
                foreach (Hashtable allapot in ((List<Hashtable>)Allapotok[l.JatekosHelye])) {
                    volt = true;
                    foreach (Point p in l.LadakHelye) {
                        if (!allapot.ContainsKey(p)) { volt = false; break; }
                    }
                    if (volt) return true;
                }
            }

            Hashtable h = new Hashtable();
            foreach (Point p in l.LadakHelye) {
                h[p] = "";
            }
            ((List<Hashtable>)Allapotok[l.JatekosHelye]).Add(h);
       
            return false;
        }

    }
}
