Source code: com/adorphuye/othello/player/AIPlayer.java
1 package com.adorphuye.othello.player;
2
3 import com.adorphuye.othello.gui.board.*;
4 import com.adorphuye.othello.*;
5 import java.awt.*;
6 import java.util.*;
7 import java.io.*;
8
9 public class AIPlayer extends Player implements BoardListener
10 {
11 private int maxlevel;
12
13 /**
14 * @return */
15 public String toString()
16 {
17 return "Computer "+getIndex();
18 }
19
20 int[][] weight= new int[][]
21 {
22 {8, 0,-7, 2,-8},
23 {2, 0,-2, 1,-6},
24 {2, 3, 1,-2, 1},
25 {1,-2, 0,-1, 0},
26 {1,-2,-1, 4, 3}
27 };
28
29 /**
30 * @param l */
31 public void setDepth(int l)
32 {
33 if(l<MIN_DEPTH || l>MAX_DEPTH)
34 {
35 throw new IllegalArgumentException("Illegal ai thinking depth: "+l);
36 }
37 maxlevel=l;
38 }
39
40 /**
41 * set the weight vector this player should use.
42 * @param w */
43 public void setweight(int[][] w)
44 {
45 weight=w;
46 }
47
48 /**
49 * @param mod
50 * @param num */
51 public AIPlayer(BoardDataModel mod, int num)
52 {
53 super(mod,num);
54 setDepth(DEFAULT_DEPTH);
55 }
56
57 private boolean shouldMove = true;
58
59 /**
60 */
61 public void play()
62 {
63 Thread t = new Thread()
64 {
65 public void run()
66 {
67 try
68 {
69 long ll = System.currentTimeMillis();
70 Point move = bestmove(getSide());
71 sleep(Math.max(250,250-(System.currentTimeMillis()-ll)));
72 if(!shouldMove)
73 {
74 shouldMove = true;
75 getModel().nextSide();
76 return;
77 }
78 if(move!=null)
79 {
80 java.util.Vector hs = getModel().flips(move,getSide());
81
82 getModel().setDataAt(move,getSide());
83
84 for(int i=0;i<hs.size();i++)
85 {
86 Point pos = (Point)hs.elementAt(i);
87 getModel().setDataAt(pos,getSide());
88 }
89 }
90 else
91 {
92 getModel().pass(AIPlayer.this);
93 }
94 getModel().nextSide();
95 }
96 catch(InterruptedException e)
97 {
98 }
99
100 }
101 };
102
103 t.start();
104 }
105
106 /**
107 * @param ob
108 * @return */
109 public Point bestmove(int ob)
110 {
111
112 Vector k=getModel().getPossibleMoves(getSide());
113
114 BoardDataModel workarea = (BoardDataModel)getModel().clone();
115
116 if(k.size()==0)
117 {
118 return null;
119 }
120
121 int best = -1;
122 int s = best;
123
124 int alpha=-100000;
125 Point tmp = null;
126 for(int i=0;i<k.size();i++)
127 {
128 tmp = (Point)k.elementAt(i);
129 //workarea.setDataAt(tmp,getSide());
130 //s=-prognosis(workarea,-100000,-alpha,1);
131
132 s = -(int)((double)worth(tmp)*((double)(workarea.flips(tmp,getSide()).size())));
133 //System.out.println("EVAL: "+tmp+" worth="+s);
134 //workarea.setDataAt(tmp,DefaultBoardDataModel.EMPTY);
135
136
137 if(s>alpha)
138 {
139 alpha=s;
140 best=i;
141 }
142 }
143 tmp = (Point)k.elementAt(best);
144 //System.out.println("Choosing "+tmp+" with worth "+worth(tmp));
145 return tmp;
146 }
147
148 /**
149 * @param workarea
150 * @param alpha
151 * @param beta
152 * @param level
153 * @return */
154 private int prognosis(BoardDataModel workarea, int alpha, int beta, int level)
155 {
156 if(level>maxlevel || workarea.getPossibleMoves(getSide()).size()==0)
157 {
158 return simplescore();
159 }
160
161 int s;
162
163 Vector k = workarea.getPossibleMoves(getSide());
164
165 for(int i=0;i<k.size();i++)
166 {
167 Point tmp = (Point)k.elementAt(i);
168 workarea.setDataAt(tmp,getSide());
169
170 s=-prognosis(workarea,-beta,-alpha,level+1);
171
172 workarea.setDataAt(tmp,DefaultBoardDataModel.EMPTY);
173
174 if(s>beta)
175 {
176 return s;
177 }
178
179 if(s>alpha)
180 {
181 alpha=s;
182 }
183 }
184
185 return alpha;
186 }
187
188 /**
189 * @param location
190 * @return */
191 private int worth(Point location)
192 {
193 try
194 {
195 return positionalValues[location.x][location.y];
196 }
197 catch(Exception e)
198 {
199 return 0;
200 }
201 }
202
203 private int[] out;
204
205 /**
206 * @return */
207 private int simplescore()
208 {
209 int score=0;
210
211 int[][] out = (int[][])positionalValues.clone();
212
213 for(int i=0;i<out.length;i++)
214 {
215 for(int j = 0;j<out[0].length;j++)
216 {
217 int o = getModel().getDataAt(new Point(i,j));
218
219 if(o != DefaultBoardDataModel.EMPTY) // if it's empty - no change in worth
220 {
221 if(o == getSide())
222 {
223 // one for us!
224 out[i][j]++;
225 }
226 else
227 {
228 // one for them :-(
229 out[i][j]--;
230 }
231 score+=out[i][j];
232 }
233 }
234 }
235
236 return score;
237 }
238
239 /**
240 * @param evt */
241 public void boardChanged(BoardEvent evt)
242 {
243 }
244
245 public void reset()
246 {
247 shouldMove = false;
248 }
249
250 private static final int[][] positionalValues = new int[][]
251 {
252 {-10, 8, 3, 3, 3, 3, 8,-10},
253 { 8, 9, 4, 7, 7, 4, 9, 8},
254 { 3, 4, 5, 8, 8, 5, 4, 3},
255 { 3, 7, 8, 9, 9, 8, 7, 3},
256 { 3, 7, 8, 9, 9, 8, 7, 3},
257 { 3, 4, 5, 8, 8, 5, 4, 3},
258 { 8, 9, 4, 7, 7, 4, 9, 8},
259 {-10, 8, 3, 3, 3, 3, 8,-10}
260 };
261 }