1 /*
2 	Copyright (c) 2008 Robin Vobruba <hoijui.quaero@gmail.com>
3 
4 	This program is free software; you can redistribute it and/or modify
5 	it under the terms of the GNU General Public License as published by
6 	the Free Software Foundation; either version 2 of the License, or
7 	(at your option) any later version.
8 
9 	This program is distributed in the hope that it will be useful,
10 	but WITHOUT ANY WARRANTY; without even the implied warranty of
11 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 	GNU General Public License for more details.
13 
14 	You should have received a copy of the GNU General Public License
15 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17 
18 package nulloojavaai;
19 
20 
21 import com.springrts.ai.AI;
22 import com.springrts.ai.oo.AIFloat3;
23 import com.springrts.ai.oo.OOAI;
24 import com.springrts.ai.oo.clb.*;
25 
26 import java.text.DateFormat;
27 import java.text.SimpleDateFormat;
28 import java.util.Date;
29 import java.util.Properties;
30 import java.util.List;
31 import java.util.logging.*;
32 
33 /**
34  * Serves as Interface for a Java Skirmish AIs for the Spring engine.
35  *
36  * @author	hoijui
37  */
38 public class NullOOJavaAI extends OOAI implements AI {
39 
40 	private static class MyCustomLogFormatter extends Formatter {
41 
42 		private DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSS dd.MM.yyyy");
43 
format(LogRecord record)44 		public String format(LogRecord record) {
45 
46 			// Create a StringBuffer to contain the formatted record
47 			// start with the date.
48 			StringBuffer sb = new StringBuffer();
49 
50 			// Get the date from the LogRecord and add it to the buffer
51 			Date date = new Date(record.getMillis());
52 			sb.append(dateFormat.format(date));
53 			sb.append(" ");
54 
55 			// Get the level name and add it to the buffer
56 			sb.append(record.getLevel().getName());
57 			sb.append(": ");
58 
59 			// Get the formatted message (includes localization
60 			// and substitution of paramters) and add it to the buffer
61 			sb.append(formatMessage(record));
62 			sb.append("\n");
63 
64 			return sb.toString();
65 		}
66 	}
67 
logProperties(Logger log, Level level, Properties props)68 	private static void logProperties(Logger log, Level level, Properties props) {
69 
70 		log.log(level, "properties (items: " + props.size() + "):");
71 		for (String key : props.stringPropertyNames()) {
72 			log.log(level, key + " = " + props.getProperty(key));
73 		}
74 	}
75 
76 	private int skirmishAIId = -1;
77 	private int teamId = -1;
78 	private Properties info = null;
79 	private Properties optionValues = null;
80 	private OOAICallback clb = null;
81 	private String myLogFile = null;
82 	private Logger log = null;
83 
84 	private static final int DEFAULT_ZONE = 0;
85 
86 
NullOOJavaAI()87 	public NullOOJavaAI() {}
88 
sendTextMsg(String msg)89 	private int sendTextMsg(String msg) {
90 
91 		try {
92 			clb.getGame().sendTextMessage(msg, DEFAULT_ZONE);
93 		} catch (Exception ex) {
94 			ex.printStackTrace();
95 			return 1;
96 		}
97 
98 		return 0;
99 	}
isDebugging()100 	public boolean isDebugging() {
101 		return true;
102 	}
103 
104 	@Override
init(int skirmishAIId, OOAICallback callback)105 	public int init(int skirmishAIId, OOAICallback callback) {
106 
107 		int ret = -1;
108 
109 		this.skirmishAIId = skirmishAIId;
110 		this.clb = callback;
111 
112 		this.teamId = clb.getSkirmishAI().getTeamId();
113 
114 		info = new Properties();
115 		Info inf = clb.getSkirmishAI().getInfo();
116 		int numInfo = inf.getSize();
117 		for (int i = 0; i < numInfo; i++) {
118 			String key = inf.getKey(i);
119 			String value = inf.getValue(i);
120 			info.setProperty(key, value);
121 		}
122 
123 		optionValues = new Properties();
124 		OptionValues opVals = clb.getSkirmishAI().getOptionValues();
125 		int numOpVals = opVals.getSize();
126 		for (int i = 0; i < numOpVals; i++) {
127 			String key = opVals.getKey(i);
128 			String value = opVals.getValue(i);
129 			optionValues.setProperty(key, value);
130 		}
131 
132 		// initialize the log
133 		try {
134 			myLogFile = callback.getDataDirs().allocatePath("log-team-" + teamId + ".txt", true, true, false, false);
135 			FileHandler fileLogger = new FileHandler(myLogFile, false);
136 			fileLogger.setFormatter(new MyCustomLogFormatter());
137 			fileLogger.setLevel(Level.ALL);
138 			log = Logger.getLogger("nulloojavaai");
139 			log.addHandler(fileLogger);
140 			if (isDebugging()) {
141 				log.setLevel(Level.ALL);
142 			} else {
143 				log.setLevel(Level.INFO);
144 			}
145 		} catch (Exception ex) {
146 			System.out.println("NullOOJavaAI: Failed initializing the logger!");
147 			ex.printStackTrace();
148 			ret = -2;
149 		}
150 
151 		try {
152 			log.info("initializing team " + teamId);
153 
154 			log.log(Level.FINE, "info:");
155 			logProperties(log, Level.FINE, info);
156 
157 			log.log(Level.FINE, "options:");
158 			logProperties(log, Level.FINE, optionValues);
159 
160 			ret = 0;
161 		} catch (Exception ex) {
162 			log.log(Level.SEVERE, "Failed initializing", ex);
163 			ret = -3;
164 		}
165 
166 		return ret;
167 	}
168 
169 	@Override
release(int reason)170 	public int release(int reason) {
171 		return 0; // signaling: OK
172 	}
173 
174 	@Override
update(int frame)175 	public int update(int frame) {
176 
177 		if (frame % 300 == 0) {
178 			sendTextMsg("listing resources ...");
179 			List<Resource> resources = clb.getResources();
180 			for (Resource resource : resources) {
181 				sendTextMsg("Resource " + resource.getName() + " optimum: "
182 						+ resource.getOptimum());
183 				sendTextMsg("Resource " + resource.getName() + " current: "
184 						+ clb.getEconomy().getCurrent(resource));
185 				sendTextMsg("Resource " + resource.getName() + " income: "
186 						+ clb.getEconomy().getIncome(resource));
187 				sendTextMsg("Resource " + resource.getName() + " storage: "
188 						+ clb.getEconomy().getStorage(resource));
189 				sendTextMsg("Resource " + resource.getName() + " usage: "
190 						+ clb.getEconomy().getUsage(resource));
191 			}
192 		}
193 
194 		return 0; // signaling: OK
195 	}
196 
197 	@Override
message(int player, String message)198 	public int message(int player, String message) {
199 		return 0; // signaling: OK
200 	}
201 
202 	@Override
unitCreated(Unit unit, Unit builder)203 	public int unitCreated(Unit unit, Unit builder) {
204 
205 		int ret = sendTextMsg("unitCreated: " + unit.toString());
206 		sendTextMsg("unitCreated def: " + unit.getDef().getName());
207 		List<UnitDef> buildOptions = unit.getDef().getBuildOptions();
208 		for (UnitDef unitDef : buildOptions) {
209 			sendTextMsg("\tbuildOption x: " + unitDef.getName() + "\t" + unitDef.getHumanName() + "\t" + unitDef.toString() + "\t" + unitDef.hashCode());
210 		}
211 
212 		return ret;
213 	}
214 
215 	@Override
unitFinished(Unit unit)216 	public int unitFinished(Unit unit) {
217 		return 0; // signaling: OK
218 	}
219 
220 	@Override
unitIdle(Unit unit)221 	public int unitIdle(Unit unit) {
222 		return 0; // signaling: OK
223 	}
224 
225 	@Override
unitMoveFailed(Unit unit)226 	public int unitMoveFailed(Unit unit) {
227 		return 0; // signaling: OK
228 	}
229 
230 	@Override
unitDamaged(Unit unit, Unit attacker, float damage, AIFloat3 dir, WeaponDef weaponDef, boolean paralyzed)231 	public int unitDamaged(Unit unit, Unit attacker, float damage, AIFloat3 dir, WeaponDef weaponDef, boolean paralyzed) {
232 		return 0; // signaling: OK
233 	}
234 
235 	@Override
unitDestroyed(Unit unit, Unit attacker)236 	public int unitDestroyed(Unit unit, Unit attacker) {
237 		return 0; // signaling: OK
238 	}
239 
240 	@Override
unitGiven(Unit unit, int oldTeamId, int newTeamId)241 	public int unitGiven(Unit unit, int oldTeamId, int newTeamId) {
242 		return 0; // signaling: OK
243 	}
244 
245 	@Override
unitCaptured(Unit unit, int oldTeamId, int newTeamId)246 	public int unitCaptured(Unit unit, int oldTeamId, int newTeamId) {
247 		return 0; // signaling: OK
248 	}
249 
250 	@Override
enemyEnterLOS(Unit enemy)251 	public int enemyEnterLOS(Unit enemy) {
252 		return 0; // signaling: OK
253 	}
254 
255 	@Override
enemyLeaveLOS(Unit enemy)256 	public int enemyLeaveLOS(Unit enemy) {
257 		return 0; // signaling: OK
258 	}
259 
260 	@Override
enemyEnterRadar(Unit enemy)261 	public int enemyEnterRadar(Unit enemy) {
262 		return 0; // signaling: OK
263 	}
264 
265 	@Override
enemyLeaveRadar(Unit enemy)266 	public int enemyLeaveRadar(Unit enemy) {
267 		return 0; // signaling: OK
268 	}
269 
270 	@Override
enemyDamaged(Unit enemy, Unit attacker, float damage, AIFloat3 dir, WeaponDef weaponDef, boolean paralyzed)271 	public int enemyDamaged(Unit enemy, Unit attacker, float damage, AIFloat3 dir, WeaponDef weaponDef, boolean paralyzed) {
272 		return 0; // signaling: OK
273 	}
274 
275 	@Override
enemyDestroyed(Unit enemy, Unit attacker)276 	public int enemyDestroyed(Unit enemy, Unit attacker) {
277 		return 0; // signaling: OK
278 	}
279 
280 	@Override
weaponFired(Unit unit, WeaponDef weaponDef)281 	public int weaponFired(Unit unit, WeaponDef weaponDef) {
282 		return 0; // signaling: OK
283 	}
284 
285 	@Override
playerCommand(java.util.List<Unit> units, int commandTopicId, int playerId)286 	public int playerCommand(java.util.List<Unit> units, int commandTopicId, int playerId) {
287 		return 0; // signaling: OK
288 	}
289 
290 	@Override
commandFinished(Unit unit, int commandId, int commandTopicId)291 	public int commandFinished(Unit unit, int commandId, int commandTopicId) {
292 		return 0; // signaling: OK
293 	}
294 
295 	@Override
seismicPing(AIFloat3 pos, float strength)296 	public int seismicPing(AIFloat3 pos, float strength) {
297 		return 0; // signaling: OK
298 	}
299 
300 	@Override
load(String file)301 	public int load(String file) {
302 		return 0; // signaling: OK
303 	}
304 
305 	@Override
save(String file)306 	public int save(String file) {
307 		return 0; // signaling: OK
308 	}
309 
310 	@Override
enemyCreated(Unit enemy)311 	public int enemyCreated(Unit enemy) {
312 		return 0; // signaling: OK
313 	}
314 
315 	@Override
enemyFinished(Unit enemy)316 	public int enemyFinished(Unit enemy) {
317 		return 0; // signaling: OK
318 	}
319 
320 }
321