001 package com.croftsoft.apps.infravision; 002 003 import java.applet.Applet; 004 import java.awt.Graphics; 005 import java.awt.*; 006 import java.awt.Color; 007 import java.awt.Point; 008 import java.awt.Rectangle; 009 010 import com.croftsoft.core.gui.plot.PlotLib; 011 import com.croftsoft.core.lang.lifecycle.Lifecycle; 012 import com.croftsoft.core.math.RandomLib; 013 014 /********************************************************************* 015 * Goblins hunt kobolds in the dark using infravision. 016 * 017 * @version 018 * 2002-03-02 019 * @since 020 * 1996-08-23 021 * @author 022 * <a href="https://www.croftsoft.com/">David Wallace Croft</a> 023 *********************************************************************/ 024 025 public class Infravision 026 extends Applet 027 implements Lifecycle, Runnable 028 ////////////////////////////////////////////////////////////////////// 029 ////////////////////////////////////////////////////////////////////// 030 { 031 032 boolean goblin_vision_on = false; 033 034 private Point lower_left = new Point ( 0, 0 ); 035 private Point upper_right = new Point ( 100, 100 ); 036 037 int walls_border_count = 2 * ( upper_right.x - lower_left.x + 1 ) 038 + 2 * ( upper_right.y - lower_left.y + 1 ) - 4; 039 int walls_count = walls_border_count + 100; 040 int goblins_count = 100; 041 int kobolds_count = 100; 042 043 boolean [ ] goblin_alive = new boolean [ goblins_count ]; 044 boolean [ ] kobold_alive = new boolean [ kobolds_count ]; 045 046 int goblins_alive_count = goblins_count; 047 int kobolds_alive_count = kobolds_count; 048 049 Point [ ] goblin_place = new Point [ goblins_count ]; 050 Point [ ] kobold_place = new Point [ kobolds_count ]; 051 Point [ ] wall_place = new Point [ walls_count ]; 052 053 Thread runner; 054 Image offscreenImage; 055 Graphics offscreenGraphics; 056 057 static final int ETHER = 0; 058 static final int WALL = 1; 059 static final int GOBLIN = 2; 060 static final int KOBOLD = 3; 061 062 private int space_contents [ ] [ ] 063 = new int [ upper_right.x - lower_left.x + 1 ] 064 [ upper_right.y - lower_left.y + 1 ]; 065 066 private Rectangle r = new Rectangle ( ); 067 068 private Point margin_top_left = new Point ( 10, 10 ); 069 private Point margin_bottom_right = new Point ( 20, 20 ); 070 071 ////////////////////////////////////////////////////////////////////// 072 ////////////////////////////////////////////////////////////////////// 073 074 public synchronized void init ( ) 075 ////////////////////////////////////////////////////////////////////// 076 { 077 r = new Rectangle ( margin_top_left.x, margin_top_left.y, 078 getSize ( ).width - margin_bottom_right.x, 079 getSize ( ).height - margin_bottom_right.y ); 080 081 offscreenImage = createImage ( getSize ( ).width, getSize ( ).height ); 082 083 offscreenGraphics = offscreenImage.getGraphics ( ); 084 085 init_walls ( ); 086 087 goblins_init ( ); 088 089 kobolds_init ( ); 090 } 091 092 public void start ( ) 093 ////////////////////////////////////////////////////////////////////// 094 { 095 runner = new Thread ( this ); 096 097 int priority = runner.getPriority ( ) - 1; 098 099 if ( priority >= Thread.MIN_PRIORITY ) 100 { 101 runner.setPriority ( priority ); 102 } 103 104 runner.setDaemon ( true ); 105 106 runner.start ( ); 107 } 108 109 public synchronized void stop ( ) 110 ////////////////////////////////////////////////////////////////////// 111 { 112 Thread thread = runner; 113 114 if ( thread != null ) 115 { 116 runner = null; 117 118 thread.interrupt ( ); 119 } 120 } 121 122 public synchronized void destroy ( ) 123 ////////////////////////////////////////////////////////////////////// 124 { 125 stop ( ); 126 } 127 128 ////////////////////////////////////////////////////////////////////// 129 ////////////////////////////////////////////////////////////////////// 130 131 public void run ( ) 132 ////////////////////////////////////////////////////////////////////// 133 { 134 Thread thread = Thread.currentThread ( ); 135 136 try 137 { 138 while ( thread == runner ) 139 { 140 kobolds_move ( ); 141 142 goblins_move ( ); 143 144 paint ( offscreenGraphics ); 145 146 Graphics g = this.getGraphics ( ); 147 148 g.drawImage ( offscreenImage, 0, 0, this ); 149 150 Thread.sleep ( 1000 ); 151 } 152 } 153 catch ( InterruptedException e ) 154 { 155 } 156 } 157 158 ////////////////////////////////////////////////////////////////////// 159 ////////////////////////////////////////////////////////////////////// 160 161 public Point goblin_move_direction ( int index_goblin ) { 162 ////////////////////////////////////////////////////////////////////// 163 Point direction = new Point ( 0, 0 ); 164 Point proposed_location = new Point ( 0, 0 ); 165 boolean target_found = false; 166 ////////////////////////////////////////////////////////////////////// 167 if ( goblin_vision_on ) { 168 outer_loop: 169 for ( int index_x = -1; 170 index_x <= 1; 171 index_x++ ) { 172 for ( int index_y = -1; 173 index_y <= 1; 174 index_y++ ) { 175 proposed_location.x = goblin_place [ index_goblin ].x + index_x; 176 proposed_location.y = goblin_place [ index_goblin ].y + index_y; 177 if ( space_contents 178 [ proposed_location.x ] 179 [ proposed_location.y ] == KOBOLD ) { 180 target_found = true; 181 direction.x = index_x; 182 direction.y = index_y; 183 break outer_loop; 184 } 185 } 186 } 187 } 188 if ( !target_found ) { 189 direction.x = ( int ) RandomLib.roll ( 1, 3, -2 ); 190 direction.y = ( int ) RandomLib.roll ( 1, 3, -2 ); 191 } 192 return new Point ( direction.x, direction.y ); 193 } 194 195 public void goblin_move ( int index_goblin ) { 196 ////////////////////////////////////////////////////////////////////// 197 boolean abort_move = false; 198 Point move_direction; 199 Point new_place = new Point ( 0, 0 ); 200 ////////////////////////////////////////////////////////////////////// 201 new_place.x = goblin_place [ index_goblin ].x; 202 new_place.y = goblin_place [ index_goblin ].y; 203 move_direction = goblin_move_direction ( index_goblin ); 204 new_place.x += move_direction.x; 205 new_place.y += move_direction.y; 206 if ( new_place.x < lower_left.x ) abort_move = true; 207 if ( new_place.x > upper_right.x ) abort_move = true; 208 if ( new_place.y < lower_left.y ) abort_move = true; 209 if ( new_place.y > upper_right.y ) abort_move = true; 210 if ( !abort_move ) { 211 if ( space_contents [ new_place.x ] [ new_place.y ] != ETHER ) { 212 if ( space_contents [ new_place.x ] [ new_place.y ] == KOBOLD ) { 213 kill_kobold ( new_place ); 214 } else abort_move = true; 215 } 216 } 217 if ( !abort_move ) { 218 space_contents 219 [ goblin_place [ index_goblin ].x ] 220 [ goblin_place [ index_goblin ].y ] = ETHER; 221 goblin_place [ index_goblin ].x = new_place.x; 222 goblin_place [ index_goblin ].y = new_place.y; 223 space_contents [ new_place.x ] [ new_place.y ] = GOBLIN; 224 } 225 } 226 227 public void goblins_move ( ) { 228 ////////////////////////////////////////////////////////////////////// 229 for ( int index_goblin = 0; 230 index_goblin < goblins_count; 231 index_goblin++ ) { 232 if ( goblin_alive [ index_goblin ] ) { 233 goblin_move ( index_goblin ); 234 } 235 } 236 } 237 238 public Point kobold_move_direction ( int index_kobold ) { 239 ////////////////////////////////////////////////////////////////////// 240 Point direction = new Point ( 0, 0 ); 241 ////////////////////////////////////////////////////////////////////// 242 direction.x = ( int ) RandomLib.roll ( 1, 3, -2 ); 243 direction.y = ( int ) RandomLib.roll ( 1, 3, -2 ); 244 return new Point ( direction.x, direction.y ); 245 } 246 247 public void kobold_move ( int index_kobold ) { 248 ////////////////////////////////////////////////////////////////////// 249 boolean abort_move = false; 250 Point move_direction; 251 Point new_place = new Point ( 0, 0 ); 252 ////////////////////////////////////////////////////////////////////// 253 new_place.x = kobold_place [ index_kobold ].x; 254 new_place.y = kobold_place [ index_kobold ].y; 255 move_direction = kobold_move_direction ( index_kobold ); 256 new_place.x += move_direction.x; 257 new_place.y += move_direction.y; 258 if ( new_place.x < lower_left.x ) abort_move = true; 259 if ( new_place.x > upper_right.x ) abort_move = true; 260 if ( new_place.y < lower_left.y ) abort_move = true; 261 if ( new_place.y > upper_right.y ) abort_move = true; 262 if ( !abort_move ) { 263 if ( space_contents [ new_place.x ] [ new_place.y ] != ETHER ) { 264 if ( space_contents [ new_place.x ] [ new_place.y ] == GOBLIN ) { 265 kill_goblin ( new_place ); 266 } else abort_move = true; 267 } 268 } 269 if ( !abort_move ) { 270 space_contents 271 [ kobold_place [ index_kobold ].x ] 272 [ kobold_place [ index_kobold ].y ] = ETHER; 273 kobold_place [ index_kobold ].x = new_place.x; 274 kobold_place [ index_kobold ].y = new_place.y; 275 space_contents [ new_place.x ] [ new_place.y ] = KOBOLD; 276 } 277 } 278 279 public void kobolds_move ( ) { 280 ////////////////////////////////////////////////////////////////////// 281 for ( int index_kobold = 0; 282 index_kobold < kobolds_count; 283 index_kobold++ ) { 284 if ( kobold_alive [ index_kobold ] ) { 285 kobold_move ( index_kobold ); 286 } 287 } 288 } 289 290 public void kill_goblin ( Point goblin_Point ) { 291 ////////////////////////////////////////////////////////////////////// 292 for ( int index_goblin = 0; 293 index_goblin < goblins_count; 294 index_goblin++ ) { 295 if ( goblin_alive [ index_goblin ] ) { 296 if ( ( goblin_place [ index_goblin ].x == goblin_Point.x ) 297 && ( goblin_place [ index_goblin ].y == goblin_Point.y ) ) { 298 goblin_alive [ index_goblin ] = false; 299 space_contents [ goblin_Point.x ] [ goblin_Point.y ] = ETHER; 300 goblins_alive_count--; 301 break; 302 } 303 } 304 } 305 } 306 307 public void kill_kobold ( Point kobold_Point ) { 308 ////////////////////////////////////////////////////////////////////// 309 for ( int index_kobold = 0; 310 index_kobold < kobolds_count; 311 index_kobold++ ) { 312 if ( kobold_alive [ index_kobold ] ) { 313 if ( ( kobold_place [ index_kobold ].x == kobold_Point.x ) 314 && ( kobold_place [ index_kobold ].y == kobold_Point.y ) ) { 315 kobold_alive [ index_kobold ] = false; 316 space_contents [ kobold_Point.x ] [ kobold_Point.y ] = ETHER; 317 kobolds_alive_count--; 318 break; 319 } 320 } 321 } 322 } 323 324 public void kobolds_init ( ) { 325 ////////////////////////////////////////////////////////////////////// 326 for ( int index_kobold = 0; 327 index_kobold < kobolds_count; 328 index_kobold++ ) { 329 do { 330 kobold_place [ index_kobold ] = new Point ( 331 ( int ) RandomLib.roll ( 332 1, upper_right.x - lower_left.x + 1, -1 ), 333 ( int ) RandomLib.roll ( 334 1, upper_right.y - lower_left.y + 1, -1 ) ); 335 } while ( space_contents 336 [ kobold_place [ index_kobold ].x ] 337 [ kobold_place [ index_kobold ].y ] != ETHER ); 338 space_contents 339 [ kobold_place [ index_kobold ].x ] 340 [ kobold_place [ index_kobold ].y ] = KOBOLD; 341 kobold_alive [ index_kobold ] = true; 342 } 343 } 344 345 public void goblins_init ( ) { 346 ////////////////////////////////////////////////////////////////////// 347 for ( int index_goblin = 0; 348 index_goblin < goblins_count; 349 index_goblin++ ) { 350 do { 351 goblin_place [ index_goblin ] = new Point ( 352 ( int ) RandomLib.roll ( 1, upper_right.x - lower_left.x + 1, -1 ), 353 ( int ) RandomLib.roll ( 1, upper_right.y - lower_left.y + 1, -1 ) ); 354 } while ( space_contents 355 [ goblin_place [ index_goblin ].x ] 356 [ goblin_place [ index_goblin ].y ] != ETHER ); 357 space_contents 358 [ goblin_place [ index_goblin ].x ] 359 [ goblin_place [ index_goblin ].y ] = GOBLIN; 360 goblin_alive [ index_goblin ] = true; 361 } 362 } 363 364 public void init_walls ( ) { 365 ////////////////////////////////////////////////////////////////////// 366 int wall_length_x = upper_right.x - lower_left.x + 1; 367 int wall_length_y = upper_right.y - lower_left.y - 1; 368 ////////////////////////////////////////////////////////////////////// 369 for ( int index_wall = 0; 370 index_wall < wall_length_x; 371 index_wall++ ) { 372 wall_place [ index_wall ] 373 = new Point ( lower_left.x + index_wall, lower_left.y ); 374 wall_place [ index_wall + wall_length_x ] 375 = new Point ( lower_left.x + index_wall, upper_right.y ); 376 space_contents 377 [ wall_place [ index_wall ].x ] 378 [ wall_place [ index_wall ].y ] = WALL; 379 space_contents 380 [ wall_place [ index_wall + wall_length_x ].x ] 381 [ wall_place [ index_wall + wall_length_x ].y ] = WALL; 382 } 383 for ( int index_wall = 0; 384 index_wall < wall_length_y; 385 index_wall++ ) { 386 wall_place [ index_wall + 2 * wall_length_x ] 387 = new Point ( lower_left.x, lower_left.y + 1 + index_wall ); 388 wall_place [ index_wall + 2 * wall_length_x + wall_length_y ] 389 = new Point ( upper_right.x, lower_left.y + 1 + index_wall ); 390 space_contents 391 [ wall_place [ index_wall + 2 * wall_length_x ].x ] 392 [ wall_place [ index_wall + 2 * wall_length_x ].y ] = WALL; 393 space_contents 394 [ wall_place [ index_wall + 2 * wall_length_x + wall_length_y ].x ] 395 [ wall_place [ index_wall + 2 * wall_length_x + wall_length_y ].y ] = WALL; 396 } 397 for ( int index_wall = walls_border_count; 398 index_wall < walls_count; 399 index_wall++ ) { 400 do { 401 wall_place [ index_wall ] = new Point ( 402 ( int ) RandomLib.roll ( 1, upper_right.x - lower_left.x + 1, -1 ), 403 ( int ) RandomLib.roll ( 1, upper_right.y - lower_left.y + 1, -1 ) ); 404 } while ( space_contents 405 [ wall_place [ index_wall ].x ] 406 [ wall_place [ index_wall ].y ] != ETHER ); 407 space_contents 408 [ wall_place [ index_wall ].x ] 409 [ wall_place [ index_wall ].y ] = WALL; 410 } 411 } 412 413 public boolean mouseDown ( Event e, int x, int y ) { 414 ////////////////////////////////////////////////////////////////////// 415 goblin_vision_on = !goblin_vision_on; 416 /* 417 for ( int index_bug = 0; 418 index_bug < bugs_max; 419 index_bug++ ) { 420 if ( bug_energy [ index_bug ] <= 0 ) { 421 double scale_x 422 = r.width / ( upper_right.x - lower_left.x + 1 ); 423 double scale_y 424 = r.height / ( upper_right.y - lower_left.y + 1 ); 425 bug_location [ index_bug ] 426 = PlotLib.graphics_to_plot_transform ( 427 new Point ( x, y ), r, this.getGraphics ( ), 428 lower_left.x, upper_right.x, lower_left.y, upper_right.y ); 429 System.out.println ( "New critter at " + bug_location [ index_bug ].x 430 + "," + bug_location [ index_bug ].y ); 431 bug_energy [ index_bug ] = baby_energy; 432 for ( int index_gene = 0; 433 index_gene < genes_max; 434 index_gene++ ) { 435 bug_genes_x [ index_bug ] [ index_gene ] 436 = ( RandomLib.roll ( 1, 2, 0 ) == 1 ); 437 bug_genes_y [ index_bug ] [ index_gene ] 438 = ( Dice.roll ( 1, 2, 0 ) == 1 ); 439 } 440 break; 441 } 442 } 443 */ 444 return true; 445 } 446 447 public void paint ( Graphics g ) { 448 ////////////////////////////////////////////////////////////////////// 449 g.setColor ( java.awt.Color.black ); 450 g.fillRect ( 0, 0, getSize ( ).width, getSize ( ).height ); 451 g.setColor ( java.awt.Color.white ); 452 // g.drawRect ( r.x, r.y, r.width, r.height ); 453 plot_kobolds ( r, g ); 454 plot_goblins ( r, g ); 455 plot_wall ( r, g ); 456 g.drawString ( 457 "Kobolds: " + kobolds_alive_count + " " + 458 "Goblins: " + goblins_alive_count + " " + 459 "Goblin vision on: " + goblin_vision_on, 460 r.x, r.y + r.height + 10 ); 461 } 462 463 public void plot_goblins ( Rectangle r, Graphics g ) { 464 ////////////////////////////////////////////////////////////////////// 465 for ( int index_goblin = 0; 466 index_goblin < goblins_count; 467 index_goblin++ ) { 468 if ( goblin_alive [ index_goblin ] ) { 469 PlotLib.xy ( java.awt.Color.magenta, 470 goblin_place [ index_goblin ].x, 471 goblin_place [ index_goblin ].y, 472 r, g, 473 lower_left.x, upper_right.x, lower_left.y, upper_right.y, 474 1, true ); 475 } 476 } 477 } 478 479 public void plot_kobolds ( Rectangle r, Graphics g ) { 480 ////////////////////////////////////////////////////////////////////// 481 for ( int index_kobold = 0; 482 index_kobold < kobolds_count; 483 index_kobold++ ) { 484 if ( kobold_alive [ index_kobold ] ) { 485 PlotLib.xy ( java.awt.Color.green, 486 kobold_place [ index_kobold ].x, 487 kobold_place [ index_kobold ].y, 488 r, g, 489 lower_left.x, upper_right.x, lower_left.y, upper_right.y, 490 1, true ); 491 } 492 } 493 } 494 495 public void plot_wall ( Rectangle r, Graphics g ) { 496 ////////////////////////////////////////////////////////////////////// 497 for ( int index_wall = 0; 498 index_wall < walls_count; 499 index_wall++ ) { 500 PlotLib.xy ( java.awt.Color.gray, 501 wall_place [ index_wall ].x, 502 wall_place [ index_wall ].y, 503 r, g, 504 lower_left.x, upper_right.x, lower_left.y, upper_right.y, 505 1, true ); 506 } 507 } 508 509 ////////////////////////////////////////////////////////////////////// 510 ////////////////////////////////////////////////////////////////////// 511 }