Changeset 48
- Timestamp:
- 04/02/10 04:33:38 (12 years ago)
- Location:
- SnowBallBot/src/snowball
- Files:
-
- 3 deleted
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
SnowBallBot/src/snowball/BotRunner.java
r47 r48 22 22 */ 23 23 public class BotRunner implements Runnable, IProtocolListener { 24 private static final Log LOG = LogFactory.getLog( BotRunner.class ); 25 26 private final Log log; 27 28 29 private static final long QUERY_INFO_TIMEOUT = 240000; //4min 30 31 //private static final long MAX_IDLE_TIMEOUT = 600000; //10min 32 33 private static final long RECONNECT_TIMEOUT = 300000; //5min 34 35 private static final double ONE_SHOT_DAMAGE = 10; 36 private static final int RECONNECT_DELAY = 10;//sec 37 38 private static final double MAX_TEMPERATURE = 37.0; 39 private static final double AVG_HEAT_ONCE = 7; 40 41 private static final int MIN_HEATER_TIMEOUT = 10000; 42 private static final int IDLE_FIGHT_DROP_TIMEOUT = 180000; 43 44 private final String name; 45 46 private final Protocol protocol; 47 48 private final IBehaviorStrategy strategy = new IBehaviorStrategy(){ 49 50 }; 51 52 private final PeopleRegistry peopleRegistry; 53 private final FightsList fights; 54 55 public BotRunner( final String name, 56 final Protocol protocol, 57 final PeopleRegistry peopleRegistry ) { 58 this.log = LogFactory.getLog( BotRunner.class.getName() + "[" + name + "]" ); 59 this.name = name; 60 this.protocol = protocol; 61 this.peopleRegistry = peopleRegistry; 62 63 protocol.addProtocolListener( this ); 64 65 enemyFinder = new EnemyFinder( 66 name, 67 peopleRegistry, 68 protocol, 69 new IPeopleFilter() { 70 public boolean appropriate( final UnitInfo u ) { 71 return isEnemyWeaker( u ) && u.experience() > 5; 72 } 73 }, 74 Commons.EXPERIENCE_COMPARATOR 75 ); 76 77 fights = new FightsList( peopleRegistry ); 78 } 79 80 private transient volatile long lastResponseProcessed = -1; 81 82 public synchronized void run() { 83 try { 84 if ( lastResponseProcessed < 0 ) { 85 log.info( "Stand up and ready for fight!" ); 86 } else { 87 if ( !reconnectIfIdle() ) { 88 final long ellapsed = System.currentTimeMillis() - lastResponseProcessed; 89 if ( ellapsed > QUERY_INFO_TIMEOUT ) { 90 log.info( "Was idle too long. Let's clearifying situation: Where am I?" ); 91 } else { 92 //just update my stats 93 } 94 } 95 } 96 queryMyInfo(); 97 } catch ( XMPPException e ) { 98 protocol.disconnect(); 99 log.error( "XMPP error", e ); 100 } catch ( Throwable t ) { 101 protocol.disconnect(); 102 log.error( "Unknown error", t ); 103 } 104 } 105 106 107 private Place place = Place.UNKNOWN; 108 109 private double temperature = 30; 110 111 private int experience = 120; 112 113 114 115 private void updateInfo( final UnitInfo info ) { 116 updatePlace( info.place() ); 117 updateTemperature( info.temperature() ); 118 this.experience = info.experience(); 119 } 120 121 private void updateTemperature( final double tmp ) { 122 this.temperature = tmp; 123 } 124 125 private void updatePlace( final Place place ) { 126 if ( this.place != place ) { 127 log.info( "place(" + this.place + " -> " + place + ")" ); 128 this.place = place; 129 if ( place != Place.STREET ) { 130 fights.outOfFight(); 131 } 132 } 133 } 134 135 public synchronized void responsed( final Response r ) { 136 try { 137 switch ( r.kind() ) { 138 case OWN_INFO: 139 final UnitInfo iam = ( UnitInfo )r.data(); 140 log.info( "\t <- info" + iam ); 141 updateInfo( iam ); 142 switch ( place ) { 143 case SNOWDRIFT: 144 case BAR: 145 if ( isEnoughHealthForFight() ) { 146 playSnowball(); 147 } else { 148 heatIfRequired(); 149 } 150 break; 151 case STREET: 152 heatIfRequired(); 153 if ( !fights.empty() ) { 154 final String name = fights.actualEnemy(); 155 if ( name != null ) { 156 attack( name ); 157 } else { 158 for ( final Fight fight : fights ) { 159 switch ( fight.state() ) { 160 case FREE: 161 case I_ATTACKED_BY_OPPONENT: 162 attack( fight.opponentName() ); 163 break; 164 case OPPONENT_ATTACKED_BY_ME: 165 final long age = fight.age(); 166 if ( age >= IDLE_FIGHT_DROP_TIMEOUT ) { 167 attack( fight.opponentName() ); 168 } else { 169 log.info( "waiting for strike back" ); 170 } 171 break; 172 default: 173 throw new IllegalStateException( "Unknown state:" + fight.state() ); 174 } 175 break; 176 } 177 } 178 } else if ( isEnoughHealthForFight() ) { 179 lookForEnemyPrefetch( true ); 180 } else { 181 if ( !canHeatAtOnce() ) { 182 hideInBar(); 183 } 184 } 185 break; 186 } 187 break; 188 case ENEMIES_LIST: { 189 final List<String> people = ( List<String> )r.data(); 190 log.info( "\t <- people(" + people.size() + ")" ); 191 peopleRegistry.updatePeopleList( people ); 192 updatePlace( Place.STREET ); 193 lookForEnemyPrefetch( false ); 194 break; 195 } 196 case ENEMY_INFO: { 197 heatIfRequired(); 198 final UnitInfo people = ( UnitInfo )r.data(); 199 peopleRegistry.update( people ); 200 log.info( "\t <- people info" + people ); 201 //dont attack if we're already on fight 202 if ( enemyFinder.isLooking() ) { 203 enemyFinder.update( people ); 204 if ( !enemyFinder.isLooking() ) { 205 final String enemy = enemyFinder.chooseOpponent(); 206 final UnitInfo info = peopleRegistry.get( enemy ); 207 log.info( "opponent choosen: " + info ); 208 attack( enemy ); 209 } 210 } else { 211 if ( peopleRegistry.isMostWanted( people.name() ) ) { 212 //todo call for help! 213 } 214 } 215 break; 216 } 217 case STREET_COME_CONFIRMED: 218 case THROWN_OUT_OF_BAR: 219 log.info( "\t <- on the street" ); 220 updatePlace( Place.STREET ); 221 heatIfRequired(); 222 if ( isEnoughHealthForFight() || canHeatAtOnce() ) { 223 final String enemy = fights.actualEnemy(); 224 if ( enemy != null ) { 225 //continue with such bastard 226 attack( enemy ); 227 } else { 228 lookForEnemyPrefetch( true ); 229 } 230 } else { 231 hideInBar(); 232 } 233 break; 234 case ENEMY_ATTACKED_CONFIRMED: 235 final String name = ( String )r.data(); 236 log.info( "\t <- attacked(" + name + ")" ); 237 updatePlace( Place.STREET ); 238 fights.attackedConfirmed( name ); 239 break; 240 case ENEMY_STRIKED_BACK: { 241 final EnemyStrikeBack eres = ( EnemyStrikeBack )r.data(); 242 updatePlace( Place.STREET ); 243 final String enemy = eres.enemyName(); 244 fights.opponentStrikedBack( enemy ); 245 temperature -= eres.ownHealthLost(); 246 247 log.info( "\t <- strike back(" + enemy + " [-" + eres.enemyHealthLost() + "]/ myself [-" + eres.ownHealthLost() + "])" ); 248 if ( isDangerous() ) { 249 log.info( "It seems to be dangerous on the street -> go bar" ); 250 tryToHideInBar(); 251 } else if ( isVeryLowHealth() ) { 252 log.info( "It seems to be cold(" + temperature + ") on the street -> go bar" ); 253 tryToHideInBar(); 254 } else { 255 heatIfRequired(); 256 attackCurrent(); 257 } 258 break; 259 } 260 case ENEMY_ESCAPED: { 261 final String enemy = ( String )r.data(); 262 updatePlace( Place.STREET ); 263 fights.opponentEscaped( enemy ); 24 private static final Log LOG = LogFactory.getLog( BotRunner.class ); 25 26 private final Log log; 27 28 29 private static final long QUERY_INFO_TIMEOUT = 240000; //4min 30 31 //private static final long MAX_IDLE_TIMEOUT = 600000; //10min 32 33 private static final long RECONNECT_TIMEOUT = 300000; //5min 34 35 private static final double ONE_SHOT_DAMAGE = 10; 36 private static final int RECONNECT_DELAY = 10;//sec 37 38 private static final double MAX_TEMPERATURE = 37.0; 39 private static final double AVG_HEAT_ONCE = 7; 40 41 private static final int MIN_HEATER_TIMEOUT = 10000; 42 private static final int IDLE_FIGHT_DROP_TIMEOUT = 180000; 43 44 private final String name; 45 46 private final Protocol protocol; 47 48 private final IBehaviorStrategy strategy = new IBehaviorStrategy() { 49 50 }; 51 52 private final PeopleRegistry peopleRegistry; 53 private final FightsList fights; 54 55 public BotRunner( final String name, 56 final Protocol protocol, 57 final PeopleRegistry peopleRegistry ) { 58 this.log = LogFactory.getLog( BotRunner.class.getName() + "[" + name + "]" ); 59 this.name = name; 60 this.protocol = protocol; 61 this.peopleRegistry = peopleRegistry; 62 63 protocol.addProtocolListener( this ); 64 65 enemyFinder = new EnemyFinder( 66 name, 67 peopleRegistry, 68 protocol, 69 new IPeopleFilter() { 70 public boolean appropriate( final UnitInfo u ) { 71 return isEnemyWeaker( u ) && u.experience() >= 0; 72 } 73 }, 74 Commons.EXPERIENCE_COMPARATOR 75 ); 76 77 fights = new FightsList( peopleRegistry ); 78 } 79 80 private transient volatile long lastResponseProcessed = -1; 81 82 public synchronized void run() { 83 try { 84 if( lastResponseProcessed < 0 ) { 85 log.info( "Stand up and ready for fight!" ); 86 } else { 87 if( !reconnectIfIdle() ) { 88 final long ellapsed = System.currentTimeMillis() - lastResponseProcessed; 89 if( ellapsed > QUERY_INFO_TIMEOUT ) { 90 log.info( "Was idle too long. Let's clearifying situation: Where am I?" ); 91 } else { 92 //just update my stats 93 } 94 } 95 } 96 queryMyInfo(); 97 } catch( XMPPException e ) { 98 protocol.disconnect(); 99 log.error( "XMPP error", e ); 100 } catch( Throwable t ) { 101 protocol.disconnect(); 102 log.error( "Unknown error", t ); 103 } 104 } 105 106 107 private Place place = Place.UNKNOWN; 108 109 private double temperature = 30; 110 111 private int experience = 120; 112 113 114 private void updateInfo( final UnitInfo info ) { 115 updatePlace( info.place() ); 116 updateTemperature( info.temperature() ); 117 this.experience = info.experience(); 118 } 119 120 private void updateTemperature( final double tmp ) { 121 this.temperature = tmp; 122 } 123 124 private void updatePlace( final Place place ) { 125 if( this.place != place ) { 126 log.info( "place(" + this.place + " -> " + place + ")" ); 127 this.place = place; 128 if( place != Place.STREET ) { 129 fights.outOfFight(); 130 } 131 } 132 } 133 134 public synchronized void responsed( final Response r ) { 135 try { 136 switch( r.kind() ) { 137 case OWN_INFO: 138 final UnitInfo iam = ( UnitInfo ) r.data(); 139 log.info( "\t <- info" + iam ); 140 updateInfo( iam ); 141 switch( place ) { 142 case SNOWDRIFT: 143 case BAR: 144 if( isEnoughHealthForFight() ) { 145 playSnowball(); 146 } else { 147 heatIfRequired(); 148 } 149 break; 150 case STREET: 151 heatIfRequired(); 152 if( !fights.empty() ) { 153 final Fight name = fights.actualEnemy(); 154 if( name != null ) { 155 attackCurrent(); 156 } else { 157 for( final Fight fight : fights ) { 158 switch( fight.state() ) { 159 case FREE: 160 case I_ATTACKED_BY_OPPONENT: 161 attack( fight.opponentName() ); 162 break; 163 case OPPONENT_ATTACKED_BY_ME: 164 final long age = fight.age(); 165 if( age >= IDLE_FIGHT_DROP_TIMEOUT ) { 166 attack( fight.opponentName() ); 167 } else { 168 log.info( "waiting for strike back" ); 169 } 170 break; 171 default: 172 throw new IllegalStateException( "Unknown state:" + fight.state() ); 173 } 174 break; 175 } 176 } 177 } else if( isEnoughHealthForFight() ) { 178 lookForEnemyPrefetch( true ); 179 } else { 180 if( !canHeatAtOnce() ) { 181 hideInBar(); 182 } 183 } 184 break; 185 } 186 break; 187 case ENEMIES_LIST: { 188 final List<String> people = ( List<String> ) r.data(); 189 log.info( "\t <- people(" + people.size() + ")" ); 190 peopleRegistry.updatePeopleList( people ); 191 updatePlace( Place.STREET ); 192 lookForEnemyPrefetch( false ); 193 break; 194 } 195 case ENEMY_INFO: { 196 heatIfRequired(); 197 final UnitInfo people = ( UnitInfo ) r.data(); 198 peopleRegistry.update( people ); 199 log.info( "\t <- people info" + people ); 200 //dont attack if we're already on fight 201 if( enemyFinder.isLooking() ) { 202 enemyFinder.update( people ); 203 if( !enemyFinder.isLooking() ) { 204 final String enemy = enemyFinder.chooseOpponent(); 205 final UnitInfo info = peopleRegistry.get( enemy ); 206 log.info( "opponent choosen: " + info ); 207 attack( enemy ); 208 } 209 } else { 210 if( peopleRegistry.isMostWanted( people.name() ) ) { 211 //todo call for help! 212 } 213 } 214 break; 215 } 216 case STREET_COME_CONFIRMED: 217 case THROWN_OUT_OF_BAR: 218 log.info( "\t <- on the street" ); 219 updatePlace( Place.STREET ); 220 heatIfRequired(); 221 if( isEnoughHealthForFight() || canHeatAtOnce() ) { 222 final Fight enemy = fights.actualEnemy(); 223 if( enemy != null ) { 224 //continue with such bastard 225 attackCurrent(); 226 } else { 227 lookForEnemyPrefetch( true ); 228 } 229 } else { 230 hideInBar(); 231 } 232 break; 233 case ENEMY_ATTACKED_CONFIRMED: 234 final String name = ( String ) r.data(); 235 log.info( "\t <- attacked(" + name + ")" ); 236 updatePlace( Place.STREET ); 237 fights.attackedConfirmed( name ); 238 break; 239 case ENEMY_STRIKED_BACK: { 240 final EnemyStrikeBack eres = ( EnemyStrikeBack ) r.data(); 241 updatePlace( Place.STREET ); 242 final String enemy = eres.enemyName(); 243 fights.opponentStrikedBack( enemy ); 244 temperature -= eres.ownHealthLost(); 245 246 log.info( "\t <- strike back(" + enemy + " [-" + eres.enemyHealthLost() + "]/ myself [-" + eres.ownHealthLost() + "])" ); 247 if( isDangerous() ) { 248 log.info( "It seems to be dangerous on the street -> go bar" ); 249 tryToHideInBar(); 250 } else if( isVeryLowHealth() ) { 251 log.info( "It seems to be cold(" + temperature + ") on the street -> go bar" ); 252 tryToHideInBar(); 253 } else { 254 heatIfRequired(); 255 attackCurrent(); 256 } 257 break; 258 } 259 case ENEMY_ESCAPED: { 260 final String enemy = ( String ) r.data(); 261 updatePlace( Place.STREET ); 262 fights.opponentEscaped( enemy ); 264 263 // temperature -= eres.ownHealthLost(); 265 264 266 267 268 269 270 271 272 273 final EnemyStrikeBack eres = ( EnemyStrikeBack )r.data();274 275 276 277 265 log.info( "\t <- escaped(" + enemy + ")" ); 266 267 heatIfRequired(); 268 attackCurrent(); 269 break; 270 } 271 case ENEMY_ESCAPING: { 272 final EnemyStrikeBack eres = ( EnemyStrikeBack ) r.data(); 273 updatePlace( Place.STREET ); 274 //updateState( State.IN_THE_FIGHT ); 275 final String enemy = eres.enemyName(); 276 fights.opponentEscaped( enemy ); 278 277 // temperature -= eres.ownHealthLost(); 279 278 280 log.info( "\t <- escaping(" + enemy + " [-" + eres.enemyHealthLost() + "])" ); 281 282 heatIfRequired(); 283 attackCurrent(); 284 break; 285 } 286 case I_AM_ATTACKED: { 287 final String enemy = ( String )r.data(); 288 fights.wasAttackedBy( enemy ); 289 log.info( "\t <- attacked by(" + enemy + ")" ); 290 updatePlace( Place.STREET ); 291 if ( fights.activeFights() == 1 ) { 292 if ( fights.size() == 1 && isEnoughHealthForFight() ) { 293 //ìî÷è óáëþäêà! 294 attack( enemy ); 295 } else { 296 //ìû íè÷åì _êðîìå_ îòâåòà íå ñâÿçàíû -- ìîæåì ñâàëèòü 297 if ( temperature > ONE_SHOT_DAMAGE ) { 298 attack( enemy ); 299 } else { 300 escape(); 301 } 302 hideInBar(); 303 } 304 } else { 305 //ïðîñòî æäåì, ïîêà îñâîáîäèìñÿ 306 //todo çâàòü íà ïîìîùü? 307 } 308 break; 309 } 310 case ENEMY_KILLED: 311 case ENEMY_NOT_AVAILABLE: { 312 final String enemy = ( String )r.data(); 313 if ( r.kind() == ENEMY_KILLED ) { 314 fights.opponentKilled( enemy ); 315 log.info( "\t <- killed(" + enemy + ")" ); 316 } else { 317 if ( enemy == null ) { 318 final Fight fight = fights.opponentNotAvailable(); 319 if ( fight != null ) { 320 log.info( "\t <- not found(" + fight.opponentName() + "?)" ); 321 } else { 322 log.info( "\t <- not found(???)" ); 323 } 324 } else { 325 fights.opponentNotAvailable( enemy ); 326 log.info( "\t <- not found(" + enemy + ")" ); 327 } 328 } 329 updatePlace( Place.STREET ); 330 //updateState( State.ON_THE_AIR ); 331 heatIfRequired(); 332 if ( isEnoughHealthForFight() || canHeatAtOnce() ) { 333 lookForEnemyPrefetch( true ); 334 } else { 335 hideInBar(); 336 } 337 break; 338 } 339 case IN_SNOWDRIFT: 340 log.info( "\t <- in snowdrift" ); 341 updatePlace( Place.SNOWDRIFT ); 342 playSnowball(); 343 break; 344 case IN_BAR: 345 log.info( "\t <- in bar" ); 346 updatePlace( Place.BAR ); 347 heatIfRequired(); 348 if ( isEnoughHealthForFight() ) { 349 playSnowball(); 350 } 351 break; 352 case HEATED_CONFIRMED: { 353 final double temp = ( Double )r.data(); 354 log.info( "\t <- heated(" + temp + ")" ); 355 updateTemperature( temp ); 356 if ( isEnoughHealthForFight() ) { 357 if ( fights.empty() ) { 358 if ( place != Place.STREET ) { 359 playSnowball(); 360 } else { 361 queryNeighbours(); 362 } 363 } else { 364 /*for( final Fight f : fights.fights() ) { 365 if( f.state() == Fight.State.I_ATTACKED_BY_OPPONENT ) { 366 attack( f.opponentName() ); 367 } 368 }*/ 369 final String opponent = fights.actualEnemy(); 370 if ( opponent != null ) { 371 attack( opponent ); 372 } 373 //todo íàäî êàê-òî ïðîäîëæèòü ñâàëêó? 374 } 375 } else { 376 if ( place == Place.STREET && fights.isFree() ) { 377 hideInBar(); 378 } 379 heatIfRequired(); 380 } 381 } 382 break; 383 case HEATER_DEPLETED: 384 log.info( "\t <- heated depeleted" ); 385 if ( place == Place.STREET ) { 386 if ( fights.empty() ) { 387 hideInBar(); 388 } 389 if ( isLowHealth() ) { 390 if ( fights.canMove() ) { 391 hideInBar(); 392 } else if ( fights.activeFights() > 1 ) { 393 tryToHideInBar(); 394 } 395 } 396 } 397 //and just wait for heater to refill 398 break; 399 case HEATER_CANT_BE_USED: 400 log.info( "\t <- can't use heater(waiting for strikeback)" ); 401 if ( place == Place.STREET ) { 402 updatePlace( Place.STREET ); 403 //just waiting for response to know, 404 //who is the enemy 405 } 406 break; 407 case REANIMATED_IN_BAR: 408 updatePlace( Place.BAR ); 409 playSnowball(); 410 updateTemperature( MAX_TEMPERATURE ); 411 break; 412 case I_AM_KILLED: { 413 final String enemy = ( String )r.data(); 414 log.info( "\t <- I was killed by (" + enemy + ")" ); 415 updatePlace( Place.REANIMATION ); 416 updateTemperature( 0 ); 417 fights.iWasKilled( enemy ); 418 //just waiting 419 break; 420 } 421 case IN_BAR_COME_CONFIRMED: 422 updatePlace( Place.BAR ); 423 heatIfRequired(); 424 if ( isEnoughHealthForFight() ) { 425 playSnowball(); 426 } 427 break; 428 case BAR_ALREADY: 429 log.info( "\t <- already in bar" ); 430 updatePlace( Place.BAR ); 431 break; 432 case SNOWDRIFT_ALREADY: 433 log.info( "\t <- already in snowdrift" ); 434 updatePlace( Place.SNOWDRIFT ); 435 break; 436 case STREET_ALREADY: 437 log.info( "\t <- already on the street" ); 438 updatePlace( Place.STREET ); 439 //todo continue fight 440 break; 441 case ENEMY_ALREADY_ATTACKED: 442 log.info( "\t <- was already attacked" ); 443 //updateState( State.ATTACKED ); 444 updatePlace( Place.STREET ); 445 break; 446 case HEATER_USELESS: 447 log.info( "\t <- heater useless (max temp)" ); 448 updateTemperature( MAX_TEMPERATURE ); 449 //nothing to do 450 break; 451 case CANT_ESCAPE: 452 log.info( "\t <- I can't escape" ); 453 updatePlace( Place.STREET ); 454 //nothing to do 455 break; 456 case I_AM_ESCAPED: 457 log.info( "\t <- I'm escaped" ); 458 updatePlace( Place.STREET ); 459 break; 460 case IN_REANIMATION: 461 log.info( "\t <- in reanimation" ); 462 updatePlace( Place.REANIMATION ); 463 updateTemperature( 0 ); 464 break; 465 case GOT_SUPERBALL: 466 log.info( "\t <- got superball. happy" ); 467 break; 468 case UNRECOGNIZED: 469 log.warn( "\t <- UNRECOGNIZED: " + r.message() ); 470 break; 471 default: 472 log.info( "\t <- NOT PROCESSED: " + r.kind() ); 473 } 474 } catch ( Throwable e ) { 475 log.error( "Error sending message", e ); 476 } finally { 477 lastResponseProcessed = System.currentTimeMillis(); 478 printState(); 479 } 480 } 481 482 private boolean tryToHideInBar() throws Exception { 483 if ( !fights.canMove() ) { 484 if ( !fights.isWaitingForOpponent() ) { 485 final boolean lowHealth = temperature / fights.activeFights() < ONE_SHOT_DAMAGE; 486 for ( final Fight fight : fights ) { 487 if ( fight.state() == Fight.State.I_ATTACKED_BY_OPPONENT ) { 488 if ( lowHealth ) { 489 escape(); 490 } else { 491 attack( fight.opponentName() ); 492 } 493 } 494 } 495 } else { 496 //continue to wait for strike back 497 return false; 498 } 499 } 500 if ( fights.canMove() ) { 501 hideInBar(); 502 heatIfRequired(); 503 return true; 504 } else { 505 return false; 506 } 507 } 508 509 private boolean isDangerous() { 510 return fights.isDangerous(); 511 } 512 513 private boolean canHeatAtOnce() { 514 return MAX_TEMPERATURE - temperature <= AVG_HEAT_ONCE; 515 } 516 517 public void escape() throws Exception { 518 protocol.escape(); 519 } 520 521 public void queryMyInfo() throws Exception { 522 protocol.queryMyInfo(); 523 log.info( " -> info(myself)" ); 524 } 525 526 public void queryNeighbours() throws Exception { 527 protocol.queryNeighbours(); 528 log.info( " -> lookAround (@" + place + ", " + temperature + ")" ); 529 } 530 531 public void playSnowball() throws Exception { 532 fights.dropOutOld( IDLE_FIGHT_DROP_TIMEOUT ); 533 protocol.play(); 534 log.info( " -> play (from " + place + ", temp " + temperature + ")" ); 535 } 536 537 private boolean isEnoughHealthForFight() { 538 return temperature >= MAX_TEMPERATURE - 4; 539 } 540 541 private boolean isLowHealth() { 542 return temperature <= MAX_TEMPERATURE / 2; 543 } 544 545 private boolean isVeryLowHealth() { 546 return temperature < ONE_SHOT_DAMAGE; 547 } 548 549 private boolean isEnemyWeaker( final UnitInfo enemy ) { 550 final double ep = Commons.enemyPower( enemy.experience() ); 551 final double mp = Commons.enemyPower( experience ); 552 return ep <= mp /*&& isEnoughHealthForFight()*/; 553 } 554 555 public void hideInBar() throws Exception { 556 protocol.moveBar(); 557 log.info( " -> bar (temp:" + temperature + ")" ); 558 } 559 560 private long lastAttack = -1; 561 562 public void attack( final String name ) throws Exception { 563 enemyFinder.clear(); 564 fights.attacked( name ); 565 protocol.attack( name ); 566 lastAttack = System.currentTimeMillis(); 567 log.info( " -> attack(" + name + ")" ); 568 } 569 570 private void attackCurrent() throws Exception { 571 if ( !fights.empty() ) { 572 // for( final Fight fight : fights.fights() ) { 573 // attack( fight.opponentName() ); 574 // break; 575 // } 576 final String enemy = fights.actualEnemy(); 577 if ( enemy != null ) { 578 attack( enemy ); 579 } 580 } else { 581 log.info( "no current enemy -- attack skipped" ); 582 } 583 } 584 585 private long lastHeaterUsed = -1; 586 587 private void heatIfRequired() throws Exception { 588 if ( !isEnoughHealthForFight() ) { 589 final long age = System.currentTimeMillis() - lastHeaterUsed; 590 if ( age <= MIN_HEATER_TIMEOUT ) { 591 //skip 592 log.info( "heater using skipped" ); 593 return; 594 } 595 if ( canHeal() ) { 596 protocol.useHeater(); 597 log.info( " -> use heater (" + temperature + ")" ); 598 lastHeaterUsed = System.currentTimeMillis(); 599 } 600 } 601 } 602 603 private boolean canHeal() { 604 switch ( place ) { 605 case BAR: 606 return true; 607 case STREET: 608 return fights.canUseHeater(); 609 case SNOWDRIFT: 610 case REANIMATION: 611 return false; 612 default: 613 throw new IllegalStateException( "Unknown place:" + place ); 614 } 615 } 616 617 private final EnemyFinder enemyFinder; 618 619 private void lookForEnemyPrefetch( final boolean forceRequery ) throws Exception { 620 if ( enemyFinder.isLooking() && !enemyFinder.isExpired() ) { 621 log.info( "Already looking for enemies -- skipped" ); 622 return; 623 } 624 625 enemyFinder.clear(); 626 if ( forceRequery || peopleRegistry.peopleListExpired() ) { 627 queryNeighbours(); 628 } else { 629 enemyFinder.investigate(); 630 } 631 } 632 633 public boolean reconnectIfIdle() { 634 final long ellapsed = System.currentTimeMillis() - lastResponseProcessed; 635 if ( ellapsed > RECONNECT_TIMEOUT ) { 636 log.info( "Too long idle -- reconnect" ); 637 reconnect(); 638 return true; 639 } else { 640 return false; 641 } 642 } 643 644 public void reconnect() { 645 protocol.disconnect(); 646 try { 647 Thread.sleep( RECONNECT_DELAY ); 648 protocol.ensureConnected(); 649 } catch ( Exception e ) { 650 log.error( "Error reconnecting", e ); 651 } 652 } 653 654 public Protocol getProtocol() { 655 return protocol; 656 } 657 658 private void printState() { 659 log.info( 660 String.format( 661 "%s(@%s, %f\u00B0, %d) %s", 662 name, 663 place, temperature, experience, 664 fights 665 ) 666 ); 667 } 668 669 public String name() { 670 return name; 671 } 672 673 @Override 674 public String toString() { 675 return String.format( 676 "%s(@%s, %f\u00B0, %d) %s", 677 name, 678 place, temperature, experience, 679 fights 680 ); 681 } 682 683 public static BotRunner startBot( final String name, 684 final PeopleRegistry peopleRegistry, 685 final Protocol protocol ) { 686 final BotRunner runner = new BotRunner( name, protocol, peopleRegistry ); 687 688 689 return runner; 690 } 279 log.info( "\t <- escaping(" + enemy + " [-" + eres.enemyHealthLost() + "])" ); 280 281 heatIfRequired(); 282 attackCurrent(); 283 break; 284 } 285 case I_AM_ATTACKED: { 286 final String enemy = ( String ) r.data(); 287 fights.wasAttackedBy( enemy ); 288 log.info( "\t <- attacked by(" + enemy + ")" ); 289 updatePlace( Place.STREET ); 290 if( fights.activeFights() == 1 ) { 291 if( fights.size() == 1 && isEnoughHealthForFight() ) { 292 //ìî÷è óáëþäêà! 293 attack( enemy ); 294 } else { 295 //ìû íè÷åì _êðîìå_ îòâåòà íå ñâÿçàíû -- ìîæåì ñâàëèòü 296 if( temperature > ONE_SHOT_DAMAGE ) { 297 attack( enemy ); 298 } else { 299 escape(); 300 } 301 hideInBar(); 302 } 303 } else { 304 //ïðîñòî æäåì, ïîêà îñâîáîäèìñÿ 305 //todo çâàòü íà ïîìîùü? 306 } 307 break; 308 } 309 case ENEMY_KILLED: 310 case ENEMY_NOT_AVAILABLE: { 311 final String enemy = ( String ) r.data(); 312 if( r.kind() == ENEMY_KILLED ) { 313 fights.opponentKilled( enemy ); 314 log.info( "\t <- killed(" + enemy + ")" ); 315 } else { 316 if( enemy == null ) { 317 final Fight fight = fights.opponentNotAvailable(); 318 if( fight != null ) { 319 log.info( "\t <- not found(" + fight.opponentName() + "?)" ); 320 } else { 321 log.info( "\t <- not found(???)" ); 322 } 323 } else { 324 fights.opponentNotAvailable( enemy ); 325 log.info( "\t <- not found(" + enemy + ")" ); 326 } 327 } 328 updatePlace( Place.STREET ); 329 heatIfRequired(); 330 if( isEnoughHealthForFight() || canHeatAtOnce() ) { 331 if( fights.empty() ) { 332 lookForEnemyPrefetch( true ); 333 } else { 334 attackCurrent(); 335 } 336 } else { 337 hideInBar(); 338 } 339 break; 340 } 341 case IN_SNOWDRIFT: 342 log.info( "\t <- in snowdrift" ); 343 updatePlace( Place.SNOWDRIFT ); 344 playSnowball(); 345 break; 346 case IN_BAR: 347 log.info( "\t <- in bar" ); 348 updatePlace( Place.BAR ); 349 heatIfRequired(); 350 if( isEnoughHealthForFight() ) { 351 playSnowball(); 352 } 353 break; 354 case HEATED_CONFIRMED: { 355 final double temp = ( Double ) r.data(); 356 log.info( "\t <- heated(" + temp + ")" ); 357 updateTemperature( temp ); 358 if( isEnoughHealthForFight() ) { 359 if( fights.empty() ) { 360 if( place != Place.STREET ) { 361 playSnowball(); 362 } else { 363 queryNeighbours(); 364 } 365 } else { 366 attackCurrent(); 367 // final Fight opponent = fights.actualEnemy(); 368 // if( opponent != null ) { 369 // attackCurrent(); 370 // } 371 //íàäî êàê-òî ïðîäîëæèòü ñâàëêó? 372 } 373 } else { 374 if( place == Place.STREET && fights.isFree() ) { 375 hideInBar(); 376 } 377 heatIfRequired(); 378 } 379 } 380 break; 381 case HEATER_DEPLETED: 382 log.info( "\t <- heated depeleted" ); 383 if( place == Place.STREET ) { 384 if( fights.empty() ) { 385 hideInBar(); 386 } 387 if( isLowHealth() ) { 388 if( fights.canMove() ) { 389 hideInBar(); 390 } else if( fights.activeFights() > 1 ) { 391 tryToHideInBar(); 392 } 393 } 394 } 395 //and just wait for heater to refill 396 break; 397 case HEATER_CANT_BE_USED: 398 log.info( "\t <- can't use heater(waiting for strikeback)" ); 399 if( place == Place.STREET ) { 400 updatePlace( Place.STREET ); 401 //just waiting for response to know, 402 //who is the enemy 403 } 404 break; 405 case REANIMATED_IN_BAR: 406 updatePlace( Place.BAR ); 407 playSnowball(); 408 updateTemperature( MAX_TEMPERATURE ); 409 break; 410 case I_AM_KILLED: { 411 final String enemy = ( String ) r.data(); 412 log.info( "\t <- I was killed by (" + enemy + ")" ); 413 updatePlace( Place.REANIMATION ); 414 updateTemperature( 0 ); 415 fights.iWasKilled( enemy ); 416 //just waiting 417 break; 418 } 419 case IN_BAR_COME_CONFIRMED: 420 updatePlace( Place.BAR ); 421 heatIfRequired(); 422 if( isEnoughHealthForFight() ) { 423 playSnowball(); 424 } 425 break; 426 case BAR_ALREADY: 427 log.info( "\t <- already in bar" ); 428 updatePlace( Place.BAR ); 429 break; 430 case SNOWDRIFT_ALREADY: 431 log.info( "\t <- already in snowdrift" ); 432 updatePlace( Place.SNOWDRIFT ); 433 break; 434 case STREET_ALREADY: 435 log.info( "\t <- already on the street" ); 436 updatePlace( Place.STREET ); 437 //todo continue fight 438 break; 439 case ENEMY_ALREADY_ATTACKED: 440 log.info( "\t <- was already attacked" ); 441 //updateState( State.ATTACKED ); 442 updatePlace( Place.STREET ); 443 break; 444 case HEATER_USELESS: 445 log.info( "\t <- heater useless (max temp)" ); 446 updateTemperature( MAX_TEMPERATURE ); 447 //nothing to do 448 break; 449 case CANT_ESCAPE: 450 log.info( "\t <- I can't escape" ); 451 updatePlace( Place.STREET ); 452 //nothing to do 453 break; 454 case I_AM_ESCAPED: 455 log.info( "\t <- I'm escaped" ); 456 updatePlace( Place.STREET ); 457 break; 458 case IN_REANIMATION: 459 log.info( "\t <- in reanimation" ); 460 updatePlace( Place.REANIMATION ); 461 updateTemperature( 0 ); 462 break; 463 case GOT_SUPERBALL: 464 log.info( "\t <- got superball. happy" ); 465 break; 466 case UNRECOGNIZED: 467 log.warn( "\t <- UNRECOGNIZED: " + r.message() ); 468 break; 469 default: 470 log.info( "\t <- NOT PROCESSED: " + r.kind() ); 471 } 472 } catch( Throwable e ) { 473 log.error( "Error sending message", e ); 474 } finally { 475 lastResponseProcessed = System.currentTimeMillis(); 476 printState(); 477 } 478 } 479 480 private boolean tryToHideInBar() throws Exception { 481 if( !fights.canMove() ) { 482 if( !fights.isWaitingForOpponent() ) { 483 final boolean lowHealth = temperature / fights.activeFights() < ONE_SHOT_DAMAGE; 484 for( final Fight fight : fights ) { 485 if( fight.state() == Fight.State.I_ATTACKED_BY_OPPONENT ) { 486 if( lowHealth ) { 487 escape(); 488 } else { 489 attack( fight.opponentName() ); 490 } 491 } 492 } 493 } else { 494 //continue to wait for strike back 495 return false; 496 } 497 } 498 if( fights.canMove() ) { 499 hideInBar(); 500 heatIfRequired(); 501 return true; 502 } else { 503 return false; 504 } 505 } 506 507 private boolean isDangerous() { 508 return fights.isDangerous(); 509 } 510 511 private boolean canHeatAtOnce() { 512 return MAX_TEMPERATURE - temperature <= AVG_HEAT_ONCE; 513 } 514 515 public void escape() throws Exception { 516 protocol.escape(); 517 } 518 519 public void queryMyInfo() throws Exception { 520 protocol.queryMyInfo(); 521 log.info( " -> info(myself)" ); 522 } 523 524 public void queryNeighbours() throws Exception { 525 protocol.queryNeighbours(); 526 log.info( " -> lookAround (@" + place + ", " + temperature + ")" ); 527 } 528 529 public void playSnowball() throws Exception { 530 fights.dropOutOld( IDLE_FIGHT_DROP_TIMEOUT ); 531 protocol.play(); 532 log.info( " -> play (from " + place + ", temp " + temperature + ")" ); 533 } 534 535 private boolean isEnoughHealthForFight() { 536 return temperature >= MAX_TEMPERATURE - 4; 537 } 538 539 private boolean isLowHealth() { 540 return temperature <= MAX_TEMPERATURE / 2; 541 } 542 543 private boolean isVeryLowHealth() { 544 return temperature < ONE_SHOT_DAMAGE; 545 } 546 547 private boolean isEnemyWeaker( final UnitInfo enemy ) { 548 final double ep = Commons.enemyPower( enemy.experience() ); 549 final double mp = Commons.enemyPower( experience ); 550 return ep <= mp /*&& isEnoughHealthForFight()*/; 551 } 552 553 public void hideInBar() throws Exception { 554 protocol.moveBar(); 555 log.info( " -> bar (temp:" + temperature + ")" ); 556 } 557 558 // private long lastAttack = -1; 559 560 public void attack( final String name ) throws Exception { 561 enemyFinder.clear(); 562 fights.attacked( name ); 563 protocol.attack( name ); 564 log.info( " -> attack(" + name + ")" ); 565 } 566 567 private void attackCurrent() throws Exception { 568 if( !fights.empty() ) { 569 final Fight fight = fights.actualEnemy(); 570 if( fight != null ) { 571 if( fight.state() != Fight.State.OPPONENT_ATTACKED_BY_ME ) { 572 attack( fight.opponentName() ); 573 } else if( fight.age() >= IDLE_FIGHT_DROP_TIMEOUT ) { 574 attack( fight.opponentName() ); 575 } else { 576 log.info( "Already attacked(" + fight.opponentName() + ") -> skipped" ); 577 } 578 } else { 579 log.info( "No current enemy -> attack skipped" ); 580 } 581 } else { 582 log.info( "No current enemy -> attack skipped" ); 583 } 584 } 585 586 private long lastHeaterUsed = -1; 587 588 private void heatIfRequired() throws Exception { 589 if( !isEnoughHealthForFight() ) { 590 final long age = System.currentTimeMillis() - lastHeaterUsed; 591 if( age <= MIN_HEATER_TIMEOUT ) { 592 //skip 593 log.info( "Too frequent heater using -> skipped" ); 594 return; 595 } 596 if( canHeal() ) { 597 protocol.useHeater(); 598 log.info( " -> use heater (" + temperature + ")" ); 599 lastHeaterUsed = System.currentTimeMillis(); 600 } 601 } 602 } 603 604 private boolean canHeal() { 605 switch( place ) { 606 case BAR: 607 return true; 608 case STREET: 609 return fights.canUseHeater(); 610 case SNOWDRIFT: 611 case REANIMATION: 612 return false; 613 default: 614 throw new IllegalStateException( "Unknown place:" + place ); 615 } 616 } 617 618 private final EnemyFinder enemyFinder; 619 620 private void lookForEnemyPrefetch( final boolean forceRequery ) throws Exception { 621 if( enemyFinder.isLooking() && !enemyFinder.isExpired() ) { 622 log.info( "Already looking for enemies -- skipped" ); 623 return; 624 } 625 626 enemyFinder.clear(); 627 if( forceRequery || peopleRegistry.peopleListExpired() ) { 628 queryNeighbours(); 629 } else { 630 enemyFinder.investigate(); 631 } 632 } 633 634 public boolean reconnectIfIdle() { 635 final long ellapsed = System.currentTimeMillis() - lastResponseProcessed; 636 if( ellapsed > RECONNECT_TIMEOUT ) { 637 log.info( "Too long idle -- reconnect" ); 638 reconnect(); 639 return true; 640 } else { 641 return false; 642 } 643 } 644 645 public void reconnect() { 646 protocol.disconnect(); 647 try { 648 Thread.sleep( RECONNECT_DELAY ); 649 protocol.ensureConnected(); 650 } catch( Exception e ) { 651 log.error( "Error reconnecting", e ); 652 } 653 } 654 655 public Protocol getProtocol() { 656 return protocol; 657 } 658 659 private void printState() { 660 log.info( 661 String.format( 662 "%s(@%s, %s\u00B0, %d) %s", 663 name, 664 place, Double.toString( temperature ), experience, 665 fights 666 ) 667 ); 668 } 669 670 public String name() { 671 return name; 672 } 673 674 @Override 675 public String toString() { 676 return String.format( 677 "%s(@%s, %s\u00B0, %d) %s", 678 name, 679 place, Double.toString( temperature ), experience, 680 fights 681 ); 682 } 683 684 public static BotRunner startBot( final String name, 685 final PeopleRegistry peopleRegistry, 686 final Protocol protocol ) { 687 final BotRunner runner = new BotRunner( name, protocol, peopleRegistry ); 688 689 690 return runner; 691 } 691 692 } -
SnowBallBot/src/snowball/Main.java
r47 r48 58 58 59 59 final String gameServer = config.getProperty( "game-address", "snow@talk2play.ru" ); 60 final String[] bots = config.getProperty( "bots", "" ).split( "\\ *s*,\\s*" );60 final String[] bots = config.getProperty( "bots", "" ).split( "\\s*,\\s*" ); 61 61 62 62 final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool( bots.length * 2 + 1 ); … … 73 73 74 74 final Protocol protocol = new Protocol( 75 tag, server, port, service,75 name, server, port, service, 76 76 login, password, 77 77 gameServer, proxyInfo -
SnowBallBot/src/snowball/helpers/FightsList.java
r46 r48 24 24 } 25 25 26 @Override27 26 public Iterator<Fight> iterator() { 28 27 return Collections.unmodifiableCollection( fights ).iterator(); … … 176 175 * "â ðàñ÷åòå" (state != FREE). Äàëåå êòî ïîïàëî 177 176 */ 178 public StringactualEnemy() {177 public Fight actualEnemy() { 179 178 if ( empty() ) { 180 179 return null; … … 182 181 for ( final Fight fight : fights ) { 183 182 if ( fight.isOpponentStarted() ) { 184 return fight .opponentName();183 return fight; 185 184 } 186 185 } 187 186 for ( final Fight fight : fights ) { 188 187 if ( fight.isOpponentActive() ) { 189 return fight .opponentName();190 } 191 } 192 193 String name= null;194 for ( final Fight fight : fights ) { 195 name = fight.opponentName();188 return fight; 189 } 190 } 191 192 Fight f = null; 193 for ( final Fight fight : fights ) { 194 f = fight; 196 195 if ( fight.state() != FREE ) { 197 return name;198 } 199 } 200 return name;196 return fight; 197 } 198 } 199 return f; 201 200 } 202 201 -
SnowBallBot/src/snowball/helpers/PeopleRegistry.java
r47 r48 15 15 */ 16 16 public class PeopleRegistry { 17 private static final Log log = LogFactory.getLog( PeopleRegistry.class ); 18 19 //private static final long EL_QUERY_EXPIRED = 180000;//3min 20 private static final int PL_EXPIRED_PERIOD = 120000; 21 //private static final int EL_EXPIRED = 120000; 22 23 /** 24 * íèêîãäà íå íàïàäàåì 25 */ 26 private static final List<String> FRIENDS = Arrays.asList( 27 "r.suhomlinov", 28 "BegemoT", 29 "cheremin", 30 "kotobaba"/*, 17 private static final Log log = LogFactory.getLog( PeopleRegistry.class ); 18 19 //private static final long EL_QUERY_EXPIRED = 180000;//3min 20 private static final int PL_EXPIRED_PERIOD = 120000; 21 //private static final int EL_EXPIRED = 120000; 22 23 /** íèêîãäà íå íàïàäàåì */ 24 private static final List<String> FRIENDS = Arrays.asList( 25 "r.suhomlinov", 26 "BegemoT", 27 "cheremin", 28 "kotobaba"/*, 31 29 "feyaolya"*/ 32 ); 33 34 /** 35 * ñàìûå, ñöóêî, ïèäîðàñû 36 */ 37 private static final List<String> MOST_WANTED = Arrays.asList( 38 "v_vasia", 39 "Orfest" 40 ); 41 42 43 /** 44 * ýòèõ ïðîñòî ïðèÿòíî ïèçäèòü 45 */ 46 private static final List<String> TOP = Arrays.asList( 47 "v_vasia", 48 "Fog", 49 "Orfest", 50 "asbest884", 51 "qwmpo", 52 "ken_88", 53 "yur4enko" 54 ); 55 56 /** 57 * åñëè äîñòóïíûõ âðàãîâ íåò -- èùåì ýòèõ 58 */ 59 private static final List<String> FIRST_CLASS_CANDIDATES = union( 60 MOST_WANTED, 61 TOP, 62 Arrays.asList( 63 "v_vasia", 64 "Orfest", 65 "tgmka", 66 "terminator", 67 "elenka_motyl", 68 "snegovik", 69 "DenisKo", 70 "Yason", 71 "whiteapt", 72 "bigh0use", 73 "440284239", 74 "spartak.cham", 75 "garik", 76 "qwmpo", 77 "Fog", 78 "asbest884", 79 "ken_88", 80 "mike", 81 "491504474", 82 "stah", 83 "m_o_z_i_a", 84 "MAKAPOH", 85 "kirdik", 86 "batora", 87 "macron" 88 ) 89 ); 90 91 private static final String STATS_FILE_NAME = "stats.txt"; 92 private static final String PARAMS_FILE_NAME = "params"; 93 94 private final List<String> peopleOnTheStreet = new ArrayList<String>(); 95 96 private volatile long peopleListTimestamp = -1; 97 private final Map<String, UnitInfo> people = new HashMap(); 98 99 private final List<UnitInfo> prioritized; 100 101 public PeopleRegistry() { 102 final File file = new File( PARAMS_FILE_NAME ); 103 List<UnitInfo> prioritized = load( file ); 104 if ( prioritized == null ) { 105 this.prioritized = new ArrayList(); 106 } else { 107 this.prioritized = prioritized; 108 for ( final UnitInfo info : prioritized ) { 109 people.put( info.name(), info ); 110 } 111 } 112 } 113 114 public boolean isMostWanted( final String name ) { 115 return MOST_WANTED.contains( name ); 116 } 117 118 public Iterable<String> mostWanted() { 119 return MOST_WANTED; 120 } 121 122 public boolean isTop( final String name ) { 123 return TOP.contains( name ); 124 } 125 126 public UnitInfo get( final String name ) { 127 return people.get( name ); 128 } 129 130 public synchronized UnitInfo update( final String name, 131 final double temp, 132 final int exp, 133 final Place place ) { 134 final UnitInfo info = new UnitInfo( name, temp, exp, place ); 135 return update( info ); 136 } 137 138 public synchronized UnitInfo update( final UnitInfo info ) { 139 people.put( info.name(), info ); 140 if ( info.place() != Place.STREET ) { 141 peopleOnTheStreet.remove( info.name() ); 142 } 143 save(); 144 return info; 145 } 146 147 public synchronized void updatePeopleList( final List<String> enemies ) { 148 peopleListTimestamp = System.currentTimeMillis(); 149 final List<String> newEnemies = new ArrayList( enemies ); 150 newEnemies.removeAll( FRIENDS ); 151 if ( !newEnemies.isEmpty() ) { 152 peopleOnTheStreet.clear(); 153 peopleOnTheStreet.addAll( newEnemies ); 154 Collections.shuffle( peopleOnTheStreet, Util.random() ); 155 } else { 156 //îñòàâëÿåì ñòàðûé ñïèñîê -- âäðóã ïðîêàòèò? 157 } 158 } 159 160 public long peopleListAge() { 161 return System.currentTimeMillis() - peopleListTimestamp; 162 } 163 164 public boolean peopleListExpired() { 165 return peopleListAge() >= PL_EXPIRED_PERIOD; 166 } 167 168 //todo prioritized candidates based on their experience 169 public synchronized List<String> suggestCandidates( final int count ) { 170 final List<String> res; 171 if ( peopleOnTheStreet.isEmpty() ) { 172 log.info( "No new enemies -- look for somebody known" ); 173 res = new ArrayList( FIRST_CLASS_CANDIDATES ); 174 } else if ( !peopleOnTheStreet.isEmpty() ) { 175 res = new ArrayList(); 176 final int len = peopleOnTheStreet.size(); 177 178 //first of all use most-wanted 179 final int cnt = Math.min( count, len ); 180 res.addAll( MOST_WANTED ); 181 182 //next choose from shuffled list 183 for ( int i = 0; i < cnt; i++ ) { 184 final String name = peopleOnTheStreet.remove( len - 1 ); 185 //and move them to the end of queue 186 peopleOnTheStreet.add( 0, name ); 187 188 res.add( name ); 189 } 190 } else { 191 res = Collections.emptyList(); 192 } 193 return res; 194 } 195 196 public synchronized String suggestNext() { 197 if ( peopleOnTheStreet.isEmpty() ) { 198 return null; 199 } else { 200 final int len = peopleOnTheStreet.size(); 201 final String last = peopleOnTheStreet.remove( len - 1 ); 202 peopleOnTheStreet.add( 0, last ); 203 return last; 204 } 205 } 206 207 public int size() { 208 return peopleOnTheStreet.size(); 209 } 210 211 private static List<String> union( final List<String>... arrs ) { 212 final Set<String> res = new HashSet<String>(); 213 for ( List<String> arr : arrs ) { 214 for ( String name : arr ) { 215 res.add( name ); 216 } 217 } 218 return Collections.unmodifiableList( new ArrayList( res ) ); 219 } 220 221 private int saveCalledCount = 0; 222 223 private static final boolean useSerialization = true; 224 225 private static List<UnitInfo> load( final File file ) { 226 final List<UnitInfo> res = new ArrayList(); 227 if ( file.exists() && file.length() > 0 ) { 228 try { 229 final FileInputStream fis = new FileInputStream( file ); 230 try { 231 if ( useSerialization ) { 232 final ObjectInputStream ois = new ObjectInputStream( fis ); 233 return ( List<UnitInfo> )ois.readObject(); 234 } else { 235 final BufferedReader r = new BufferedReader( new InputStreamReader( fis ) ); 236 try { 237 final String line = r.readLine(); 238 final String[] parts = line.split( "\\s*,\\s*" ); 239 final String name = parts[0]; 240 final int exp = Integer.parseInt( parts[1] ); 241 final double temp = Double.parseDouble( parts[2] ); 242 final Place place = Place.valueOf( parts[3] ); 243 res.add( new UnitInfo( name, temp, exp, place ) ); 244 } finally { 245 r.close(); 246 } 247 } 248 } finally { 249 fis.close(); 250 } 251 } catch ( Exception e ) { 252 log.error( "can't load params", e ); 253 } 254 } 255 return res; 256 } 257 258 private synchronized void save() { 259 saveCalledCount++; 260 if ( saveCalledCount % 5 == 0 ) { 261 prioritized.clear(); 262 prioritized.addAll( people.values() ); 263 Collections.sort( prioritized, Commons.EXPERIENCE_COMPARATOR ); 264 try { 265 final FileWriter fw = new FileWriter( STATS_FILE_NAME ); 266 try { 267 for ( UnitInfo unit : prioritized ) { 268 fw.write( 269 String.format( 270 "%s, %d, %f, %s\n", 271 unit.name(), 272 unit.experience(), 273 unit.temperature(), 274 unit.place() 275 ) 276 ); 277 } 278 } finally { 279 fw.close(); 280 } 281 final OutputStream fos = new FileOutputStream( PARAMS_FILE_NAME ); 282 try { 283 final ObjectOutputStream oos = new ObjectOutputStream( fos ); 284 oos.writeObject( prioritized ); 285 oos.flush(); 286 } finally { 287 fos.close(); 288 } 289 } catch ( IOException e ) { 290 log.error( "IO", e ); 291 } 292 } 293 } 30 ); 31 32 /** ñàìûå, ñöóêî, ïèäîðàñû */ 33 private static final List<String> MOST_WANTED = Arrays.asList( 34 "v_vasia", 35 "Orfest" 36 ); 37 38 39 /** ýòèõ ïðîñòî ïðèÿòíî ïèçäèòü */ 40 private static final List<String> TOP = Arrays.asList( 41 "v_vasia", 42 "Fog", 43 "Orfest", 44 "asbest884", 45 "qwmpo", 46 "ken_88", 47 "yur4enko" 48 ); 49 50 /** åñëè äîñòóïíûõ âðàãîâ íåò -- èùåì ýòèõ */ 51 private static final List<String> FIRST_CLASS_CANDIDATES = union( 52 MOST_WANTED, 53 TOP, 54 Arrays.asList( 55 "v_vasia", 56 "Orfest", 57 "tgmka", 58 "terminator", 59 "elenka_motyl", 60 "snegovik", 61 "DenisKo", 62 "Yason", 63 "whiteapt", 64 "bigh0use", 65 "440284239", 66 "spartak.cham", 67 "garik", 68 "qwmpo", 69 "Fog", 70 "asbest884", 71 "ken_88", 72 "mike", 73 "491504474", 74 "stah", 75 "m_o_z_i_a", 76 "MAKAPOH", 77 "kirdik", 78 "batora", 79 "macron" 80 ) 81 ); 82 83 private static final String STATS_FILE_NAME = "stats.txt"; 84 private static final String PARAMS_FILE_NAME = "params"; 85 86 private final List<String> peopleOnTheStreet = new ArrayList<String>(); 87 88 private final Map<String, UnitInfo> people = new HashMap(); 89 private final List<UnitInfo> prioritized; 90 91 private volatile long peopleListTimestamp = -1; 92 93 public PeopleRegistry() { 94 final File file = new File( PARAMS_FILE_NAME ); 95 this.prioritized = load( file ); 96 for( final UnitInfo info : prioritized ) { 97 people.put( info.name(), info ); 98 } 99 } 100 101 public boolean isMostWanted( final String name ) { 102 return MOST_WANTED.contains( name ); 103 } 104 105 public Iterable<String> mostWanted() { 106 return MOST_WANTED; 107 } 108 109 public boolean isTop( final String name ) { 110 return TOP.contains( name ); 111 } 112 113 public UnitInfo get( final String name ) { 114 return people.get( name ); 115 } 116 117 public synchronized UnitInfo update( final String name, 118 final double temp, 119 final int exp, 120 final Place place ) { 121 final UnitInfo info = new UnitInfo( name, temp, exp, place ); 122 return update( info ); 123 } 124 125 public synchronized UnitInfo update( final UnitInfo info ) { 126 people.put( info.name(), info ); 127 if( info.place() != Place.STREET ) { 128 peopleOnTheStreet.remove( info.name() ); 129 } 130 save(); 131 return info; 132 } 133 134 public synchronized void updatePeopleList( final List<String> enemies ) { 135 peopleListTimestamp = System.currentTimeMillis(); 136 final List<String> newEnemies = new ArrayList( enemies ); 137 newEnemies.removeAll( FRIENDS ); 138 if( !newEnemies.isEmpty() ) { 139 peopleOnTheStreet.clear(); 140 peopleOnTheStreet.addAll( newEnemies ); 141 Collections.shuffle( peopleOnTheStreet, Util.random() ); 142 } else { 143 //îñòàâëÿåì ñòàðûé ñïèñîê -- âäðóã ïðîêàòèò? 144 } 145 } 146 147 public long peopleListAge() { 148 return System.currentTimeMillis() - peopleListTimestamp; 149 } 150 151 public boolean peopleListExpired() { 152 return peopleListAge() >= PL_EXPIRED_PERIOD; 153 } 154 155 //todo prioritized candidates based on their experience 156 public synchronized List<String> suggestCandidates( final int count ) { 157 final List<String> res; 158 if( peopleOnTheStreet.isEmpty() ) { 159 log.info( "No new enemies -- look for somebody known" ); 160 res = new ArrayList( FIRST_CLASS_CANDIDATES ); 161 } else if( !peopleOnTheStreet.isEmpty() ) { 162 res = new ArrayList(); 163 final int len = peopleOnTheStreet.size(); 164 165 //first of all use most-wanted 166 final int cnt = Math.min( count, len ); 167 res.addAll( MOST_WANTED ); 168 169 //next choose from shuffled list 170 for( int i = 0; i < cnt; i++ ) { 171 final String name = peopleOnTheStreet.remove( len - 1 ); 172 //and move them to the end of queue 173 peopleOnTheStreet.add( 0, name ); 174 175 res.add( name ); 176 } 177 } else { 178 res = Collections.emptyList(); 179 } 180 return res; 181 } 182 183 public synchronized String suggestNext() { 184 if( peopleOnTheStreet.isEmpty() ) { 185 return null; 186 } else { 187 final int len = peopleOnTheStreet.size(); 188 final String last = peopleOnTheStreet.remove( len - 1 ); 189 peopleOnTheStreet.add( 0, last ); 190 return last; 191 } 192 } 193 194 public int size() { 195 return peopleOnTheStreet.size(); 196 } 197 198 private static List<String> union( final List<String>... arrs ) { 199 final Set<String> res = new HashSet<String>(); 200 for( List<String> arr : arrs ) { 201 for( String name : arr ) { 202 res.add( name ); 203 } 204 } 205 return Collections.unmodifiableList( new ArrayList( res ) ); 206 } 207 208 private int saveCalledCount = 0; 209 210 private static final boolean useSerialization = false; 211 212 private static List<UnitInfo> load( final File file ) { 213 final List<UnitInfo> res = new ArrayList(); 214 if( file.exists() && file.length() > 0 ) { 215 try { 216 final FileInputStream fis = new FileInputStream( file ); 217 try { 218 if( useSerialization ) { 219 final ObjectInputStream ois = new ObjectInputStream( fis ); 220 return ( List<UnitInfo> ) ois.readObject(); 221 } else { 222 final BufferedReader r = new BufferedReader( new InputStreamReader( fis ) ); 223 try { 224 final String line = r.readLine(); 225 final String[] parts = line.split( "\\s*,\\s*" ); 226 final String name = parts[0]; 227 final int exp = Integer.parseInt( parts[1] ); 228 final double temp = Double.parseDouble( parts[2] ); 229 final Place place = Place.valueOf( parts[3] ); 230 res.add( new UnitInfo( name, temp, exp, place ) ); 231 } finally { 232 r.close(); 233 } 234 } 235 } finally { 236 fis.close(); 237 } 238 } catch( Exception e ) { 239 log.error( "can't load params", e ); 240 } 241 } 242 return res; 243 } 244 245 private synchronized void save() { 246 saveCalledCount++; 247 if( saveCalledCount % 5 == 0 ) { 248 prioritized.clear(); 249 prioritized.addAll( people.values() ); 250 Collections.sort( prioritized, Commons.EXPERIENCE_COMPARATOR ); 251 final File file = new File( PARAMS_FILE_NAME ); 252 try { 253 if( false/*useSerialization */ ) { 254 final OutputStream fos = new FileOutputStream( file ); 255 try { 256 final ObjectOutputStream oos = new ObjectOutputStream( fos ); 257 oos.writeObject( prioritized ); 258 oos.flush(); 259 } finally { 260 fos.close(); 261 } 262 } else { 263 final FileWriter fw = new FileWriter( file ); 264 try { 265 for( UnitInfo unit : prioritized ) { 266 fw.write( 267 String.format( 268 "%s, %d, %s, %s\n", 269 unit.name(), 270 unit.experience(), 271 Double.toString( unit.temperature() ), 272 unit.place() 273 ) 274 ); 275 } 276 } finally { 277 fw.close(); 278 } 279 } 280 } catch( IOException e ) { 281 log.error( "IO", e ); 282 } 283 } 284 } 294 285 }
Note: See TracChangeset
for help on using the changeset viewer.