1 2=head1 NAME 3 4Mines::Field - A minesweeper field 5 6=head1 SYNOPSIS 7 8 # setup field properties 9 $P0 = new 'Hash' 10 $P0['width'] = 40 11 $P0['height'] = 28 12 $P0['mines'] = 0.1075 13 $P0['level'] = 123 14 $P0['screen'] = screen 15 $P0['debug'] = debug 16 17 # create the field 18 field = new "Mines::Field", $P0 19 20 # draw the field 21 field.'draw'() 22 23=head1 DESCRIPTION 24 25This is an implementation of a Minesweeper game field. 26It draws the field onto a SDL surface. 27 28=head1 METHODS 29 30An Mines::Field object has the following methods: 31 32=over 4 33 34=cut 35 36.include "iterator.pasm" 37.loadlib 'math_ops' 38.namespace ["Mines::Field"] 39 40# size of a single mine field, in pixels 41.const int FIELD_WIDTH = 16 42.const int FIELD_HEIGHT = 16 43 44# mine field values 45.const int VAL_INVALID = -1 46.const int VAL_FREE = 0 47.const int VAL_1 = 1 48.const int VAL_2 = 2 49.const int VAL_3 = 3 50.const int VAL_4 = 4 51.const int VAL_5 = 5 52.const int VAL_6 = 6 53.const int VAL_7 = 7 54.const int VAL_8 = 8 55.const int VAL_MINE_EXPLODED = 9 56.const int VAL_NO_MINE = 10 57.const int VAL_MINE = 11 58.const int VAL_FLAG_NO_MINE = 12 59.const int VAL_FLAG_MINE = 13 60.const int VAL_UNSURE_NO_MINE = 14 61.const int VAL_UNSURE_MINE = 15 62.const int VAL_UNEXPLORED_NO_MINE = 16 63.const int VAL_UNEXPLORED_MINE = 17 64.const int VAL_MARK_NO_MINE = 18 65.const int VAL_MARK_MINE = 19 66 67# game status 68.const int STATUS_PLAYING = 0 69.const int STATUS_CHOOSING = 1 70.const int STATUS_LOST = 2 71.const int STATUS_SLEEPING = 3 72.const int STATUS_WON = 4 73 74 75=item __init( hash ) 76 77The constructor. You have to pass a hash filled with 78the following values: 79 80=over 4 81 82=item width 83 84Number of horizontal units the field should have. 85 86=item height 87 88Number of vertical units the field should have. 89 90=item level 91 92Initial seed for the PRNG that is used to calculate the field. 93 94=item mines 95 96The amount of mines. 0.0 means no mines, 1.0 means mines everywhere. 97 98=item screen 99 100SDL surface to use for drawing. 101 102=item debug 103 1040 = normal mode 1051 = use debug image (position of mines are visible) 106 107=back 108 109=cut 110 111.sub __init :method 112 .param pmc args 113 .local pmc field 114 .local pmc screen 115 .local pmc cache 116 .local int width 117 .local int height 118 .local int level 119 .local num mines 120 .local int val 121 .local int debug 122 .local pmc lcd 123 .local pmc watch 124 125 # get the arguments 126 width = args['width'] 127 height = args['height'] 128 level = args['level'] 129 mines = args['mines'] 130 screen = args['screen'] 131 debug = args['debug'] 132 field = new 'ResizablePMCArray' 133 cache = new 'ResizablePMCArray' 134 135 watch = new ['SDL'; 'StopWatch'], screen 136 watch.'xpos'( 515 ) 137 watch.'ypos'( 5 ) 138 139 lcd = new ['SDL'; 'LCD'] 140 # This seems to call __init() with too many parameters 141 # lcd = 0 142 lcd.'_digits'( 4 ) 143 lcd.'xpos'( 5 ) 144 lcd.'ypos'( 5 ) 145 146 setattribute self, 'field', field 147 setattribute self, 'cache', cache 148 setattribute self, 'screen', screen 149 setattribute self, 'mines_lcd', lcd 150 setattribute self, 'watch', watch 151 152 $P0 = new 'Integer' 153 $P0 = width 154 setattribute self, 'width', $P0 155 156 $P0 = new 'Integer' 157 $P0 = height 158 setattribute self, 'height', $P0 159 160 $P0 = new 'Float' 161 $P0 = mines 162 setattribute self, 'mines', $P0 163 164 $P0 = new 'Integer' 165 $P0 = -1 166 setattribute self, 'markpos', $P0 167 168 $P0 = new 'Integer' 169 $P0 = debug 170 setattribute self, 'debug', $P0 171 172 # button 173 $P0 = new 'String' 174 $P0 = "examples/sdl/minesweeper/smiley.png" 175 $P0 = new ['SDL'; 'Button'], $P0 176 $P0.'states'( 5 ) 177 $P0.'pos'( 305, 2 ) 178 $P0.'size'( 30, 30 ) 179 180 $P1 = get_hll_global [ 'Mines::Field' ], '_button_clicked' 181 $P0.'setAction'( STATUS_PLAYING, $P1 ) 182 $P0.'setAction'( STATUS_WON, $P1 ) 183 $P0.'setAction'( STATUS_LOST, $P1 ) 184 185 setattribute self, 'status_button', $P0 186 187 self.'newLevel'( level ) 188.end 189 190=item newLevel( level ) 191 192Creates a new level, with the given number as initial seed for the PRNG. 193 194=cut 195 196.sub newLevel :method 197 .param int level 198 .local pmc field 199 .local pmc cache 200 .local int size 201 .local int width 202 .local int height 203 .local int val 204 .local num mines 205 206 field = getattribute self, 'field' 207 cache = getattribute self, 'cache' 208 209 $P0 = getattribute self, 'witdh' 210 width = $P0 211 212 $P0 = getattribute self, 'height' 213 height = $P0 214 215 $P0 = getattribute self, 'mines' 216 mines = $P0 217 218 size = width * height 219 220 field = 0 221 cache = 0 222 223 # fill the field 224LOOP: 225 level += size 226 227 $I0 = level 228 shl $I0, 13 229 $I0 = or $I0, level 230 231 $I1 = $I0 * $I0 232 $I1 *= 15731 233 $I1 += 789221 234 235 $I1 *= $I0 236 $I1 += 1376312589 237 238 $N0 = $I1 239 $N0 = $N0 / 1073741824.0 240 $N0 = 100.0 + $N0 241 $N0 *= 100.0 242 $I0 = $N0 243 $N0 = $N0 - $I0 244 level += $I0 245 246 val = VAL_UNEXPLORED_NO_MINE 247 ge $N0, mines, NO_MINE 248 val = VAL_UNEXPLORED_MINE 249NO_MINE: 250 251 push field, val 252 push cache, VAL_INVALID 253 254 dec size 255 if size <= 0 goto END 256 branch LOOP 257END: 258 # set the game status 259 self.'setStatus'( STATUS_PLAYING ) 260 # reset the watch 261 $P0 = getattribute self, "Mines::Field\x0watch" 262 $P0.'reset'() 263.end 264 265=item draw() 266 267Draws the field, then the LCDs and the smiley button. 268 269=cut 270 271.sub draw :method 272 .local pmc screen 273 .local pmc image 274 .local pmc dest_rect 275 .local pmc src_rect 276 .local int width 277 .local int height 278 .local int size 279 .local int i 280 .local pmc field 281 .local pmc cache 282 .local pmc cacheit 283 .local int debug 284 .local int minx 285 .local int miny 286 .local int maxx 287 .local int maxy 288 .local pmc mines_lcd 289 .local pmc watch 290 .local pmc status 291 292 getattribute field, self, 'field' 293 field = iter field 294 field = .ITERATE_FROM_START 295 296 cache = getattribute self, 'cache' 297 cacheit = iter cache 298 cacheit = .ITERATE_FROM_START 299 300 screen = getattribute self, 'screen' 301 302 $P0 = getattribute self, 'width' 303 width = $P0 304 305 $P0 = getattribute self, 'height' 306 height = $P0 307 308 $P0 = getattribute self, 'debug' 309 debug = $P0 310 311 minx = width * FIELD_WIDTH 312 miny = height * FIELD_HEIGHT 313 maxx = 0 314 maxy = 0 315 316 if debug goto DEBUG 317 image = get_hll_global [ "Mines::Field" ], "field" 318 branch IMAGE_OK 319DEBUG: 320 image = get_hll_global [ "Mines::Field" ], "field_debug" 321IMAGE_OK: 322 $P0 = new 'Hash' 323 $P0['x'] = 0 324 $P0['y'] = 0 325 $P0['width'] = 0 326 $P0['height'] = 0 327 dest_rect = new ['SDL'; 'Rect'], $P0 328 $P0['width'] = FIELD_WIDTH 329 $P0['height'] = FIELD_HEIGHT 330 src_rect = new ['SDL'; 'Rect'], $P0 331 332 set size, width 333 mul size, height 334 335 i = 0 336LOOP: 337 if i >= size goto END 338 339 $P0 = shift field 340 $I0 = $P0 341 $P0 = shift cacheit 342 $I1 = $P0 343 344 # current field already drawn? 345 if $I0 == $I1 goto NEXT 346 347 cache[i] = $I0 348 349 $I1 = cmod i, width 350 $I2 = div i, width 351 352 mul $I1, FIELD_WIDTH 353 mul $I2, FIELD_HEIGHT 354 355 add $I1, 0 356 add $I2, 32 357 358 dest_rect.'x'( $I1 ) 359 dest_rect.'y'( $I2 ) 360 361 if $I1 > minx goto SKIP1 362 minx = $I1 363SKIP1: 364 365 if $I2 > miny goto SKIP2 366 miny = $I2 367SKIP2: 368 369 if $I1 < maxx goto SKIP3 370 maxx = $I1 371SKIP3: 372 373 if $I2 < maxy goto SKIP4 374 maxy = $I2 375SKIP4: 376 377 $I1 = cmod $I0, 5 378 $I2 = div $I0, 5 379 380 mul $I1, FIELD_WIDTH 381 mul $I2, FIELD_HEIGHT 382 383 src_rect.'x'( $I1 ) 384 src_rect.'y'( $I2 ) 385 386 screen.'blit'( image, src_rect, dest_rect ) 387NEXT: 388 inc i 389 branch LOOP 390END: 391 392 add maxx, FIELD_WIDTH 393 add maxy, FIELD_HEIGHT 394 395 if maxx <= minx goto NO_SCREEN_UPDATE 396 if maxy <= miny goto NO_SCREEN_UPDATE 397 398 dest_rect.'x'( minx ) 399 dest_rect.'y'( miny ) 400 $I0 = maxx - minx 401 dest_rect.'width'( $I0 ) 402 $I0 = maxy - miny 403 dest_rect.'height'( $I0 ) 404 405 screen.'update_rect'( dest_rect ) 406NO_SCREEN_UPDATE: 407 408 # update the LCDs 409 self.'update_stats'() 410 411 $P0 = getattribute self, "Mines::Field\x0mines_lcd" 412 $P0.'draw'( screen ) 413 414 $P0 = getattribute self, "Mines::Field\x0watch" 415 $P0.'draw'( screen ) 416 417 $P0 = getattribute self, "Mines::Field\x0status_button" 418 $P0.'draw'( screen ) 419.end 420 421=item reveal( x, y ) 422 423Reveals the field at the specified location. 424 425Returns 1 if successful, 0 otherwise. 426 427=cut 428 429.sub reveal :method 430 .param int x 431 .param int y 432 .local int width 433 .local int height 434 .local pmc watch 435 436 self."undo_mark"() 437 438 $P0 = getattribute self, 'width' 439 width = $P0 440 441 $P0 = getattribute self, 'height' 442 height = $P0 443 444 watch = getattribute self, 'watch' 445 446 $P0 = getattribute self, 'status' 447 if $P0 > STATUS_CHOOSING goto END 448 449 x -= 0 450 y -= 32 451 452 if x < 0 goto END 453 if y < 0 goto END 454 455 x /= FIELD_WIDTH 456 y /= FIELD_HEIGHT 457 458 watch.'start'() 459 self.'reveal_recursive'( x, y, width, height ) 460 self.'check_end'() 461 self.'draw'() 462 463 .return (1) 464 465END: 466 .return (0) 467.end 468 469=item setFlag( x, y ) 470 471Sets a flag at the specified location. 472 473Returns 1 if successful, 0 otherwise. 474 475=cut 476 477.sub setFlag :method 478 .param int x 479 .param int y 480 .local int width 481 .local pmc field 482 .local pmc watch 483 .local int pos 484 .local int v 485 486 self."undo_mark"() 487 488 $P0 = getattribute self, 'field' 489 field = $P0 490 491 $P0 = getattribute self, 'width' 492 width = $P0 493 494 watch = getattribute self, 'watch' 495 496 $P0 = getattribute self, 'status' 497 if $P0 > STATUS_CHOOSING goto END 498 499 x -= 0 500 y -= 32 501 502 if x < 0 goto END 503 if y < 0 goto END 504 505 x /= FIELD_WIDTH 506 y /= FIELD_HEIGHT 507 508 pos = y * width 509 pos += x 510 511 v = field[pos] 512 513 if v == VAL_FLAG_NO_MINE goto PLUS2 514 if v == VAL_FLAG_MINE goto PLUS2 515 if v == VAL_UNSURE_NO_MINE goto PLUS2 516 if v == VAL_UNSURE_MINE goto PLUS2 517 if v == VAL_UNEXPLORED_NO_MINE goto MINUS4 518 if v == VAL_UNEXPLORED_MINE goto MINUS4 519 branch END 520 521PLUS2: 522 v += 2 523 branch DRAW 524 525MINUS4: 526 v -= 4 527 528DRAW: 529 field[pos] = v 530 531 watch.'start'() 532 self."check_end"() 533 self."draw"() 534 535 .return (1) 536 537END: 538 .return (0) 539.end 540 541=item undo_mark( i ) B<(internal)> 542 543Removes the field mark. 544 545Parameters: 546 547=over 4 548 549=item i 550 551Optional. The value does not matter. If you pass an integer value, 552the game status is not set. If you pass no integer, the game status 553will be set. 554 555Just do not pass an integer, it is for internal use only. 556(C<setStatus()> calls undo_mark, which in turn calls setStatus; this 557argument is used to avoid recursion) 558 559=back 560 561This method returns nothing. 562 563=cut 564 565.sub undo_mark :method 566 .param int i :optional 567 .param int has_i :opt_flag 568 569 .local pmc markpos 570 .local pmc field 571 .local pmc status 572 573 $P0 = getattribute self, 'field' 574 field = $P0 575 576 markpos = getattribute self, 'markpos' 577 status = getattribute self, 'status' 578 579 $I0 = markpos 580 581 if $I0 == -1 goto UNDO_DONE 582 $I1 = field[$I0] 583 $I1 -= 2 584 field[$I0] = $I1 585UNDO_DONE: 586 markpos = -1 587 588 if has_i goto END 589 if status != STATUS_CHOOSING goto END 590 self."setStatus"( STATUS_PLAYING ) 591END: 592.end 593 594=item mark( x, y ) 595 596Sets a mark on the specified field. 597This is used to give feedback which field will be revealed. 598Only one field is marked at any time, a previous mark will be 599removed if you call this method. 600 601=cut 602 603.sub mark :method 604 .param int x 605 .param int y 606 .local int width 607 .local pmc markpos 608 .local pmc field 609 .local pmc watch 610 .local int pos 611 .local int v 612 613 self."undo_mark"() 614 615 $P0 = getattribute self, 'field' 616 field = $P0 617 618 $P0 = getattribute self, 'width' 619 width = $P0 620 621 markpos = getattribute self, 'markpos' 622 623 x -= 0 624 y -= 32 625 626 watch = getattribute self, 'watch' 627 628 $P0 = getattribute self, 'status' 629 if $P0 >= STATUS_CHOOSING goto END 630 631 if x < 0 goto END 632 if y < 0 goto END 633 634 x /= FIELD_WIDTH 635 y /= FIELD_HEIGHT 636 637 pos = y * width 638 pos += x 639 640 v = field[pos] 641 642 if v == VAL_UNEXPLORED_NO_MINE goto MARK 643 if v == VAL_UNEXPLORED_MINE goto MARK 644 branch END 645MARK: 646 self."setStatus"( STATUS_CHOOSING ) 647 markpos = pos 648 v += 2 649 field[pos] = v 650DRAW: 651 watch.'start'() 652 self."check_end"() 653 self."draw"() 654 655 .return (1) 656 657END: 658 .return (0) 659.end 660 661=item click( x, y, b ) 662 663This method is used to send mouse click events to the smiley button. 664 665Parameters: 666 667=over 4 668 669=item x 670 671The vertical mouse position. 672 673=item y 674 675The horizontal mouse position. 676 677=item b 678 6790 = mouse button not pressed 680 6811 = mouse button pressed 682 683=back 684 685=cut 686 687.sub click :method 688 .param int x 689 .param int y 690 .param int b 691 692 if y > 32 goto END 693 694 $P0 = getattribute self, 'status_button' 695 $I0 = $P0.'click'( x, y, b, self ) 696 unless $I0 goto END 697 698 $P1 = getattribute self, 'screen' 699 700 $P0."draw"( $P1 ) 701END: 702 703.end 704 705=item reveal_recursive( x, y, width, height ) B<(internal)> 706 707Reveals the specified field recursively. 708 709The width and height are the dimensions of the board, they 710have to be specified for performance reasons. 711 712=cut 713 714.sub reveal_recursive :method 715 .param int x 716 .param int y 717 .param int width 718 .param int height 719 .local pmc field 720 .local int pos 721 722 if x < 0 goto END 723 if y < 0 goto END 724 if x >= width goto END 725 if y >= height goto END 726 727 pos = y * width 728 pos += x 729 730 $P0 = getattribute self, 'field' 731 field = $P0 732 733 $I0 = field[pos] 734 if $I0 == VAL_FREE goto END 735 if $I0 == VAL_UNEXPLORED_NO_MINE goto UNEXPLORED 736 if $I0 == VAL_UNEXPLORED_MINE goto UNEXPLORED_MINE 737 branch END 738 739UNEXPLORED: 740 $I0 = _mines_near( field, x, y, width, height ) 741 field[pos] = $I0 742 if $I0 != 0 goto END 743 744 dec y 745 dec x 746 self.'reveal_recursive'( x, y, width, height ) 747 inc x 748 self.'reveal_recursive'( x, y, width, height ) 749 inc x 750 self.'reveal_recursive'( x, y, width, height ) 751 752 inc y 753 dec x 754 dec x 755 self.'reveal_recursive'( x, y, width, height ) 756 inc x 757 self.'reveal_recursive'( x, y, width, height ) 758 inc x 759 self.'reveal_recursive'( x, y, width, height ) 760 761 inc y 762 dec x 763 dec x 764 self.'reveal_recursive'( x, y, width, height ) 765 inc x 766 self.'reveal_recursive'( x, y, width, height ) 767 inc x 768 self.'reveal_recursive'( x, y, width, height ) 769 branch END 770 771UNEXPLORED_MINE: 772 field[pos] = VAL_MINE_EXPLODED 773 self.'lost'() 774 775END: 776 .return () 777.end 778 779=item lost() 780 781Called if a mine is revealed. 782Shows the position of all mines on the field. 783 784=cut 785 786.sub lost :method 787 .local pmc field 788 .local int i 789 .local int max 790 791 self."setStatus"( STATUS_LOST ) 792 793 field = getattribute self, 'field' 794 max = field 795 i = 0 796 797LOOP: 798 if i >= max goto END 799 800 $I1 = field[i] 801 802 if $I1 == VAL_UNEXPLORED_MINE goto MINE 803 if $I1 == VAL_UNSURE_MINE goto MINE 804 if $I1 == VAL_FLAG_NO_MINE goto NO_MINE 805 branch NEXT 806 807MINE: 808 $I1 = VAL_MINE 809 branch NEXT 810 811NO_MINE: 812 $I1 = VAL_NO_MINE 813 branch NEXT 814 815NEXT: 816 field[i] = $I1 817 inc i 818 branch LOOP 819END: 820.end 821 822=item won() 823 824Called when you have won. 825 826=cut 827 828.sub won :method 829 self."setStatus"( STATUS_WON ) 830.end 831 832=item check_end() 833 834Checks if you have won. 835 836=cut 837 838.sub check_end :method 839 .local pmc field 840 841 field = getattribute self, 'field' 842 field = iter field 843 field = .ITERATE_FROM_START 844LOOP: 845 unless field goto WON 846 847 $I0 = shift field 848 849 if $I0 <= 8 goto LOOP 850 851 if $I0 == VAL_MINE goto END 852 if $I0 == VAL_MINE_EXPLODED goto END 853 if $I0 == VAL_UNSURE_MINE goto END 854 if $I0 == VAL_FLAG_NO_MINE goto END 855 if $I0 == VAL_UNEXPLORED_MINE goto END 856 857 branch LOOP 858 859WON: 860 self."won"() 861 .return (1) 862END: 863 .return (0) 864.end 865 866=item setStatus( newStatus ) 867 868Sets a new game status. 869 870=cut 871 872.sub setStatus :method 873 .param int s 874 .local pmc screen 875 .local pmc watch 876 .local pmc status 877 878 screen = getattribute self, 'screen' 879 watch = getattribute self, 'watch' 880 status = getattribute self, 'status' 881 882 if s == STATUS_PLAYING goto OK 883 if s == STATUS_CHOOSING goto OK 884 885 # not playing at the moment, stop the watch 886 watch.'stop'() 887OK: 888 # no need to start the watch here 889 890 status = s 891 self."undo_mark"( 1 ) 892 watch.'draw'( screen ) 893 894DONE: 895.end 896 897=item update_stats() 898 899Counts the unrevealed mines and updates the LCD. 900 901=cut 902 903.sub update_stats :method 904 .local pmc field 905 .local int size 906 .local pmc count 907 .local pmc mines_lcd 908 909 field = getattribute self, 'field' 910 mines_lcd = getattribute self, 'mines_lcd' 911 912 size = field 913 field = iter field 914 field = .ITERATE_FROM_START 915 count = new 'ResizablePMCArray' 916 917LOOP: 918 unless field goto END 919 $I0 = shift field 920 $I1 = count[$I0] 921 inc $I1 922 count[$I0] = $I1 923 branch LOOP 924END: 925 926 $I0 = count[VAL_UNEXPLORED_MINE] 927 $I1 = count[VAL_UNSURE_MINE] 928 $I2 = count[VAL_FLAG_NO_MINE] 929 $I3 = count[VAL_MINE] 930 $I4 = count[VAL_MINE_EXPLODED] 931 $I5 = count[VAL_MARK_MINE] 932 933 $I0 += $I1 934 $I0 -= $I2 935 $I0 += $I3 936 $I0 += $I4 937 $I0 += $I5 938 mines_lcd = $I0 939.end 940 941=back 942 943=head1 INTERNAL FUNCTIONS 944 945=over 4 946 947=item __onload() 948 949Loads necessary modules and creates the B<Mines::Field> class. 950This method is called automatically when this module is loaded. 951 952=cut 953 954.sub __onload :load 955 .local pmc class 956 class = get_class "Mines::Field" 957 unless null class goto END 958 959 .local pmc tmp 960 .local pmc size 961 .local pmc size_rect 962 .local pmc prop 963 964 .local pmc from_rect 965 .local pmc image 966 .local int rect_type 967 .local int surface_type 968 969 load_bytecode "examples/sdl/minesweeper/eventhandler.pir" 970 load_bytecode "SDL/Button.pir" 971 load_bytecode "SDL/StopWatch.pir" 972 load_bytecode "SDL/Image.pir" 973 974 # XXX: remove 975 load_bytecode "Data/Dumper.pir" 976 977 $P0 = new 'String' 978 $P0 = "examples/sdl/minesweeper/mines.png" 979 image = new ['SDL'; 'Image'], $P0 980 set_hll_global [ "Mines::Field" ], "field", image 981 982 $P0 = new 'String' 983 $P0 = "examples/sdl/minesweeper/mines_debug.png" 984 image = new ['SDL'; 'Image'], $P0 985 set_hll_global [ "Mines::Field" ], "field_debug", image 986 987 newclass $P0, "Mines::Field" 988 addattribute $P0, 'field' 989 addattribute $P0, 'cache' 990 addattribute $P0, 'screen' 991 addattribute $P0, 'width' 992 addattribute $P0, 'height' 993 addattribute $P0, 'mines' 994 addattribute $P0, 'markpos' 995 addattribute $P0, 'debug' 996 addattribute $P0, 'mines_lcd' 997 addattribute $P0, 'watch' 998 addattribute $P0, 'status_button' 999END: 1000.end 1001 1002=item _mines_near( field, x, y, width, height ) 1003 1004Returns the number of mines in the neighbourhood 1005of the field at the specified location. 1006 1007The width and height are the dimensions of the board. 1008 1009=cut 1010 1011.sub _mines_near 1012 .param pmc field 1013 .param int x 1014 .param int y 1015 .param int width 1016 .param int height 1017 .local int mines 1018 .local int i 1019 .local int i1 1020 .local int i2 1021 .local int j 1022 .local int j2 1023 .local int pos 1024 1025 mines = 0 1026 1027 set i1, x 1028 dec i1 1029 set i2, x 1030 inc i2 1031 1032 set j, y 1033 dec j 1034 set j2, y 1035 inc j2 1036 1037LOOPj: 1038 i = i1 1039LOOPi: 1040 if i > i2 goto ENDi 1041 if j < 0 goto ENDi 1042 if j >= height goto ENDi 1043 if i < 0 goto NEXTi 1044 if i >= width goto NEXTi 1045 1046 pos = j * width 1047 pos += i 1048 1049 $I0 = _mine_at( field, pos ) 1050 unless $I0 goto NEXTi 1051 1052 inc mines 1053 1054NEXTi: 1055 inc i 1056 branch LOOPi 1057ENDi: 1058 inc j 1059 if j <= j2 goto LOOPj 1060 1061 .return (mines) 1062.end 1063 1064=item _mine_at( field, pos ) 1065 1066Returns 1 if a mine is in the given field 1067at the specified position, 0 otherwise. 1068 1069=cut 1070 1071.sub _mine_at 1072 .param pmc field 1073 .param int pos 1074 .local int v 1075 1076 v = field[pos] 1077 if v == VAL_MINE goto MINE 1078 if v == VAL_MINE_EXPLODED goto MINE 1079 if v == VAL_FLAG_MINE goto MINE 1080 if v == VAL_UNSURE_MINE goto MINE 1081 if v == VAL_UNEXPLORED_MINE goto MINE 1082 if v == VAL_MARK_MINE goto MINE 1083 .return (0) 1084MINE: 1085 .return (1) 1086.end 1087 1088=item _button_clicked( onField ) 1089 1090Called if you click the smiley button. 1091It starts a new level. 1092 1093=cut 1094 1095.sub _button_clicked 1096 .param pmc field 1097 1098 $I0 = time 1099 field.'newLevel'( $I0 ) 1100 field.'draw'() 1101.end 1102 1103=back 1104 1105=head1 AUTHOR 1106 1107Jens Rieks E<lt>parrot at jensbeimsurfen dot deE<gt> is the author 1108and maintainer. 1109Please send patches and suggestions to the Perl 6 Internals mailing list. 1110 1111=head1 COPYRIGHT 1112 1113Copyright (C) 2004-2008, Parrot Foundation. 1114 1115=cut 1116 1117# Local Variables: 1118# mode: pir 1119# fill-column: 100 1120# End: 1121# vim: expandtab shiftwidth=4 ft=pir: 1122