/*
 *  Copyright 2002-2009 Mikhail Kryshen <mikhail@kryshen.net>
 *
 *  This file is part of BMTron.
 *
 *  BMTron is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  BMTron is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BMTron.  If not, see <http://www.gnu.org/licenses/>.
 */

package kryshen.bmtron;

import java.awt.Color;
import java.awt.Point;

/**
 * Weird AI algorithm.
 */
public class ComputerPlayer2 extends ThreadedPlayer {
    private int[][] field2;
    
    private float k1 = 1f;
    private float k2 = 1f;
    
    private boolean firstMove = true;
    
    ComputerPlayer2(Field field, String name, Color color, int team) {
        super(field, name, color, team);
    }
    
    synchronized void start() {
        firstMove = true;
        super.start();
    }
    
    protected void move() {
        if (firstMove) {
            firstMove = false;
            setDirection(randomMove());
            return;
        }
            
        k1 = 1f - (Game.random.nextFloat() * 0.2f);
        k2 = (Game.random.nextFloat() * 2f) + 2f;

        Point l = getLocation();
        int dir = field.UP;
        
        float lr, lr2;
    
        lr = calcArea(l.x, l.y - 1, l.x, l.y + 1);
        lr2 = calcArea(l.x - 1, l.y, l.x + 1, l.y);
        boolean r = (Game.nextRandom(0, 1) == 1);
        if (lr2 > lr || (r && lr2 == lr)) {
            dir = field.LEFT;
            lr = lr2;
        }
        lr2 = calcArea(l.x, l.y + 1, l.x, l.y - 1);
        r = (Game.nextRandom(0, 1) == 1);
        if (lr2 > lr || (r && lr2 == lr)) {
            dir = field.DOWN;
            lr = lr2;
        }
        lr2 = calcArea(l.x + 1, l.y, l.x - 1, l.y);
        r = (Game.nextRandom(0, 1) == 1);
        if (lr2 > lr || (r && lr2 == lr)) {
            dir = field.RIGHT;
            lr = lr2;
        }
        
        setDirection(dir);
    }
    
    private void resetField2() {
        field2 = new int[50][35];
        
        for (int i = 0; i < field.players.length; i++) {
            if (field.players[i].team != team && 
                !field.players[i].isStoped()) {
                
                Point p = field.players[i].getLocation();
                
                int x1 = p.x - 3; 
                if (x1 < 0) x1 = 0;
                
                int y1 = p.y - 3;
                if (y1 < 0) y1 = 0;
                
                int x2 = p.x + 3;
                if (x2 > field.cols - 1) x2 = field.cols - 1;
                
                int y2 = p.y + 3;
                if (y2 > field.rows - 1) y2 = field.rows - 1;
                
                for (int ix = x1; ix <= x2; ix++) {
                    for (int iy = y1; iy <= y2; iy++) {
                        if (Math.abs(ix - p.x) <= 1 && 
                            Math.abs(iy - p.y) <= 1) {
                            
                            field2[ix][iy] = -1;
                        } else {
                            field2[ix][iy] = 2;
                        }
                    }
                }                
            }
        }
    }
        
    private float calcArea(int x, int y, int bx, int by) {
        if (!field.isFree(x, y)) { 
            return Float.NEGATIVE_INFINITY;
        }

        resetField2();
        return calcArea_Rec(x, y, bx, by);
    }

    private float calcArea_Rec(int x, int y, int bx, int by) {
        if (!field.isFree(x, y))
            return -1f;
        
        if (Math.abs(x - bx) == Math.abs(y - by) || field2[x][y] == 1)
            return 0f;
        
        float area = 2f;        
        
        boolean b = (field2[x][y] < 0);
        boolean b2 = (field2[x][y] >= 2);
        
        field2[x][y] = 1;
                
        float a1 = calcArea_Rec(x, y - 1, bx, by);
        float a2 = calcArea_Rec(x, y + 1, bx, by);
        
        if (a1 == -1f && a2 == -1f && (b || b2))
            return -100f;
        
        area += a1 + a2;
                
        a1 = calcArea_Rec(x - 1, y, bx, by);
        a2 = calcArea_Rec(x + 1, y, bx, by);
        
        if (a1 == -1 && a2 == -1 && (b || b2))
            return -100f;
        
        area += a1 + a2;
        
        if (b)
            area = area * k1;
        else if (b2)
            area = area * k2;

        return area;
    }
}
