=head1 NAME

Mines::Field - A minesweeper field

=head1 SYNOPSIS

    # setup field properties
    $P0 = new .Hash
    $P0['width']  = 40
    $P0['height'] = 28
    $P0['mines']  = 0.1075
    $P0['level']  = 123
    $P0['screen'] = screen
    $P0['debug']  = debug

    # create the field
    $I0 = find_type "Mines::Field"
    field = new $I0, $P0

    # draw the field
    field.'draw'()

=head1 DESCRIPTION

This is an implementation of a Minesweeper game field.
It draws the field onto a SDL surface.

=head1 METHODS

An Mines::Field object has the following methods:

=over 4

=cut

.include "iterator.pasm"
.namespace ["Mines::Field"]

# size of a single mine field, in pixels
.const int FIELD_WIDTH  = 16
.const int FIELD_HEIGHT = 16

# mine field values
.const int VAL_INVALID            = -1
.const int VAL_FREE               =  0
.const int VAL_1                  =  1
.const int VAL_2                  =  2
.const int VAL_3                  =  3
.const int VAL_4                  =  4
.const int VAL_5                  =  5
.const int VAL_6                  =  6
.const int VAL_7                  =  7
.const int VAL_8                  =  8
.const int VAL_MINE_EXPLODED      =  9
.const int VAL_NO_MINE            = 10
.const int VAL_MINE               = 11
.const int VAL_FLAG_NO_MINE       = 12
.const int VAL_FLAG_MINE          = 13
.const int VAL_UNSURE_NO_MINE     = 14
.const int VAL_UNSURE_MINE        = 15
.const int VAL_UNEXPLORED_NO_MINE = 16
.const int VAL_UNEXPLORED_MINE    = 17
.const int VAL_MARK_NO_MINE       = 18
.const int VAL_MARK_MINE          = 19

# game status
.const int STATUS_PLAYING  = 0
.const int STATUS_CHOOSING = 1
.const int STATUS_LOST     = 2
.const int STATUS_SLEEPING = 3
.const int STATUS_WON      = 4


=item __init( hash )

The constructor. You have to pass a hash filled with
the following values:

=over 4

=item width

Number of horizontal units the field should have.

=item height

Number of vertical units the field should have.

=item level

Initial seed for the PRNG that is used to calulate the field.

=item mines

The amount of mines. 0.0 means no mines, 1.0 means mines everywhere.

=item screen

SDL surface to use for drawing.

=item debug

0 = normal mode
1 = use debug image (position of mines are visible)

=back

=cut

.sub __init method
    .param pmc args
    .local pmc field
    .local pmc screen
    .local pmc cache
    .local int width
    .local int height
    .local int level
    .local num mines
    .local int val
    .local int debug
    .local pmc lcd
    .local pmc watch

    # get the arguments
    width  = args['width']
    height = args['height']
    level  = args['level']
    mines  = args['mines']
    screen = args['screen']
    debug  = args['debug']
    field  = new .ResizablePMCArray
    cache  = new .ResizablePMCArray

    $I0 = find_type 'SDL::StopWatch'
    watch = new $I0, screen
    watch.'xpos'( 515 )
    watch.'ypos'( 5 )

    $I0 = find_type 'SDL::LCD'
    lcd = new $I0
    # This seems to call __init() with too many parameters
    # lcd = 0
    lcd.'_digits'( 4 )
    lcd.'xpos'( 5 )
    lcd.'ypos'( 5 )

    # set the attributes
    $I0 = classoffset self, 'Mines::Field'

    # field
    setattribute self, $I0, field

    # cache
    inc $I0
    setattribute self, $I0, cache

    # screen
    inc $I0
    setattribute self, $I0, screen

    # width
    inc $I0
    $P0 = new .Integer
    $P0 = width
    setattribute self, $I0, $P0
    
    # height
    inc $I0
    $P0 = new .Integer
    $P0 = height
    setattribute self, $I0, $P0

    # mines
    inc $I0
    $P0 = new .Float
    $P0 = mines
    setattribute self, $I0, $P0

    # markpos
    inc $I0
    $P0 = new .Integer
    $P0 = -1
    setattribute self, $I0, $P0

    # debug
    inc $I0
    $P0 = new .Integer
    $P0 = debug
    setattribute self, $I0, $P0

    # lcd
    inc $I0
    setattribute self, $I0, lcd

    # watch
    inc $I0
    setattribute self, $I0, watch

    # button
    inc $I0
    $P0 = new .String
    $P0 = "examples/sdl/minesweeper/smiley.png"
    $I1 = find_type "SDL::Button"
    $P0 = new $I1, $P0
    $P0.'states'( 5 )
    $P0.'pos'( 305, 2 )
    $P0.'size'( 30, 30 )
    
    $P1 = find_global 'Mines::Field', '_button_clicked'
    $P0.'setAction'( STATUS_PLAYING, $P1 )
    $P0.'setAction'( STATUS_WON, $P1 )
    $P0.'setAction'( STATUS_LOST, $P1 )
    
    setattribute self, $I0, $P0

    self.'newLevel'( level )
.end

=item newLevel( level )

Creates a new level, with the given number as initial seed for the PRNG.

=cut

.sub newLevel method
    .param int level
    .local pmc field
    .local pmc cache
    .local int size
    .local int width
    .local int height
    .local int val
    .local num mines

    # get the attributes
    $I0 = classoffset self, 'Mines::Field'

    # field
    field = getattribute self, $I0

    # cache
    inc $I0
    cache = getattribute self, $I0

    # width
    add $I0, 2
    $P0 = getattribute self, $I0
    width = $P0
    
    # height
    inc $I0
    $P0 = getattribute self, $I0
    height = $P0

    # mines
    inc $I0
    $P0 = getattribute self, $I0
    mines = $P0

    size = width * height

    field = 0
    cache = 0
    
    # fill the field
LOOP:
    level += size
    
    $I0 = level
    shl $I0, 13
    $I0 = or $I0, level
    
    $I1 = $I0 * $I0
    $I1 *= 15731
    $I1 += 789221

    $I1 *= $I0
    $I1 += 1376312589

    $N0 = $I1
    $N0 = $N0 / 1073741824.0
    $N0 = 100.0 + $N0
    $N0 *= 100.0
    $I0 = $N0
    $N0 = $N0 - $I0
    level += $I0
    
    val = VAL_UNEXPLORED_NO_MINE
    ge $N0, mines, NO_MINE
    val = VAL_UNEXPLORED_MINE
NO_MINE:

    push field, val
    push cache, VAL_INVALID
        
    dec size
    if size <= 0 goto END
    branch LOOP
END:
    # set the game status
    self.'setStatus'( STATUS_PLAYING )
    # reset the watch
    $P0 = getattribute self, "Mines::Field\x0watch"
    $P0.'reset'()
.end

=item draw()

Draws the field, then the LCDs and the smiley button.

=cut

.sub draw method
    .local pmc screen
    .local pmc image
    .local pmc dest_rect
    .local pmc src_rect
    .local int width
    .local int height
    .local int size
    .local int i
    .local pmc field
    .local pmc cache
    .local pmc cacheit
    .local int debug
    .local int minx
    .local int miny
    .local int maxx
    .local int maxy
    .local pmc mines_lcd
    .local pmc watch
    .local pmc status

    classoffset $I0, self, "Mines::Field"

    # field
    getattribute field, self, $I0
    field = new Iterator, field
    field = .ITERATE_FROM_START

    # cache
    inc $I0
    cache = getattribute self, $I0
    cacheit = new Iterator, cache
    cacheit = .ITERATE_FROM_START

    # screen
    inc $I0
    screen = getattribute self, $I0
    
    # width
    inc $I0
    $P0 = getattribute self, $I0
    width = $P0

    # height
    inc $I0
    $P0 = getattribute self, $I0
    height = $P0

    # debug
    add $I0, 3
    $P0 = getattribute self, $I0
    debug = $P0

    minx = width * FIELD_WIDTH
    miny = height * FIELD_HEIGHT
    maxx = 0
    maxy = 0

    if debug goto DEBUG
    image = find_global "Mines::Field", "field"
    branch IMAGE_OK
DEBUG:
    image = find_global "Mines::Field", "field_debug"
IMAGE_OK:
    $I0 = find_type "SDL::Rect"
    $P0 = new .Hash
    $P0['x'] = 0
    $P0['y'] = 0
    $P0['width']  = 0
    $P0['height'] = 0
    dest_rect = new $I0, $P0
    $P0['width']  = FIELD_WIDTH
    $P0['height'] = FIELD_HEIGHT
    src_rect = new $I0, $P0

    set size, width
    mul size, height

    i = 0
LOOP:
    if i >= size goto END

    $P0 = shift field
    $I0 = $P0
    $P0 = shift cacheit
    $I1 = $P0
    
    # current field already drawn?
    if $I0 == $I1 goto NEXT

    cache[i] = $I0

    $I1 = cmod i, width
    $I2 = div i, width
    
    mul $I1, FIELD_WIDTH
    mul $I2, FIELD_HEIGHT
    
    add $I1, 0
    add $I2, 32

    dest_rect.'x'( $I1 )
    dest_rect.'y'( $I2 )

    if $I1 > minx goto SKIP1
    minx = $I1
SKIP1:

    if $I2 > miny goto SKIP2
    miny = $I2
SKIP2:

    if $I1 < maxx goto SKIP3
    maxx = $I1
SKIP3:

    if $I2 < maxy goto SKIP4
    maxy = $I2
SKIP4:
    
    $I1 = cmod $I0, 5
    $I2 = div $I0, 5

    mul $I1, FIELD_WIDTH
    mul $I2, FIELD_HEIGHT
    
    src_rect.'x'( $I1 )
    src_rect.'y'( $I2 )
    
    screen.'blit'( image, src_rect, dest_rect )
NEXT:
    inc i
    branch LOOP
END:

    add maxx, FIELD_WIDTH
    add maxy, FIELD_HEIGHT

    if maxx <= minx goto NO_SCREEN_UPDATE
    if maxy <= miny goto NO_SCREEN_UPDATE
    
    dest_rect.'x'( minx )
    dest_rect.'y'( miny )
    $I0 = maxx - minx
    dest_rect.'width'( $I0 )
    $I0 = maxy - miny
    dest_rect.'height'( $I0 )

    screen.'update_rect'( dest_rect )
NO_SCREEN_UPDATE:

    # update the LCDs
    self.'update_stats'()

    $P0 = getattribute self, "Mines::Field\x0mines_lcd"
    $P0.'draw'( screen )

    $P0 = getattribute self, "Mines::Field\x0watch"
    $P0.'draw'( screen )

    $P0 = getattribute self, "Mines::Field\x0status_button"
    $P0.'draw'( screen )
.end

=item reveal( x, y )

Reveals the field at the specified location.

Returns 1 if successful, 0 otherwise.

=cut

.sub reveal method
    .param int x
    .param int y
    .local int width
    .local int height
    .local pmc watch

    self."undo_mark"()
            
    $I0 = classoffset self, 'Mines::Field'

    # width
    add $I0, 3
    $P0 = getattribute self, $I0
    width = $P0

    # height
    inc $I0
    $P0 = getattribute self, $I0
    height = $P0

    # watch
    add $I0, 5
    watch = getattribute self, $I0
    
    # status
    inc $I0
    $P0 = getattribute self, $I0
    if $P0 > STATUS_CHOOSING goto END
    
    x -= 0
    y -= 32

    if x < 0 goto END
    if y < 0 goto END
    
    x /= FIELD_WIDTH
    y /= FIELD_HEIGHT    
        
    watch.'start'()
    self.'reveal_recursive'( x, y, width, height )
    self.'check_end'()
    self.'draw'()

    .pcc_begin_return
    .return 1
    .pcc_end_return

END:
    .pcc_begin_return
    .return 0
    .pcc_end_return
.end

=item setFlag( x, y )

Sets a flag at the specified location.

Returns 1 if successful, 0 otherwise.

=cut

.sub setFlag method
    .param int x
    .param int y
    .local int width
    .local pmc field
    .local pmc watch
    .local int pos
    .local int v

    self."undo_mark"()
    
    $I0 = classoffset self, 'Mines::Field'

    # field
    $P0 = getattribute self, $I0
    field = $P0

    # width
    add $I0, 3
    $P0 = getattribute self, $I0
    width = $P0

    # watch
    add $I0, 6
    watch = getattribute self, $I0
    
    # status
    inc $I0
    $P0 = getattribute self, $I0
    if $P0 > STATUS_CHOOSING goto END

    x -= 0
    y -= 32

    if x < 0 goto END
    if y < 0 goto END

    x /= FIELD_WIDTH
    y /= FIELD_HEIGHT
    
    pos = y * width
    pos += x
    
    v = field[pos]

    if v == VAL_FLAG_NO_MINE goto PLUS2
    if v == VAL_FLAG_MINE goto PLUS2
    if v == VAL_UNSURE_NO_MINE goto PLUS2
    if v == VAL_UNSURE_MINE goto PLUS2
    if v == VAL_UNEXPLORED_NO_MINE goto MINUS4
    if v == VAL_UNEXPLORED_MINE goto MINUS4
    branch END

PLUS2:
    v += 2
    branch DRAW
    
MINUS4:
    v -= 4
    
DRAW:
    field[pos] = v

    watch.'start'()
    self."check_end"()
    self."draw"()

    .pcc_begin_return
    .return 1
    .pcc_end_return

END:
    .pcc_begin_return
    .return 0
    .pcc_end_return
.end

=item undo_mark( i ) B<(internal)>

Removes the field mark.

Parameters:

=over 4

=item i

Optional. The value does not matter. If you pass an integer value,
the game status is not set. If you pass no integer, the game status
will be set.

Just do not pass an integer, it is for internal use only.
(C<setStatus()> calls undo_mark, which in turn calls setStatus; this
argument is used to avoid recursion)

=back

This method returns nothing.

=cut

.sub undo_mark method
    .param int i      :optional
    .param int has_i  :opt_flag

    .local pmc markpos
    .local pmc field
    .local pmc status
    
    
    $I0 = classoffset self, 'Mines::Field'

    # field
    $P0 = getattribute self, $I0
    field = $P0

    # markpos
    add $I0, 6
    markpos = getattribute self, $I0

    # status
    add $I0, 4
    status = getattribute self, $I0

    $I0 = markpos
    if $I0 == -1 goto UNDO_DONE
    $I1 = field[$I0]
    $I1 -= 2
    field[$I0] = $I1
UNDO_DONE:
    markpos = -1

    if has_i goto END
    if status != STATUS_CHOOSING goto END
    self."setStatus"( STATUS_PLAYING )
END:
.end

=item mark( x, y )

Sets a mark on the specified field.
This is used to give feedback which field will be revealed.
Only one field is marked at any time, a previous mark will be
removed if you call this method.

=cut

.sub mark method
    .param int x
    .param int y
    .local int width
    .local pmc markpos
    .local pmc field
    .local pmc watch
    .local int pos
    .local int v
    
    self."undo_mark"()
    
    $I0 = classoffset self, 'Mines::Field'

    # field
    $P0 = getattribute self, $I0
    field = $P0

    # width
    add $I0, 3
    $P0 = getattribute self, $I0
    width = $P0

    # markpos
    add $I0, 3
    markpos = getattribute self, $I0

    x -= 0
    y -= 32

    # watch
    add $I0, 3
    watch = getattribute self, $I0
    
    # status
    inc $I0
    $P0 = getattribute self, $I0
    if $P0 >= STATUS_CHOOSING goto END

    if x < 0 goto END
    if y < 0 goto END

    x /= FIELD_WIDTH
    y /= FIELD_HEIGHT
    
    pos = y * width
    pos += x

    v = field[pos]

    if v == VAL_UNEXPLORED_NO_MINE goto MARK
    if v == VAL_UNEXPLORED_MINE goto MARK
    branch END
MARK:
    self."setStatus"( STATUS_CHOOSING )
    markpos = pos
    v += 2
    field[pos] = v
DRAW:
    watch.'start'()
    self."check_end"()
    self."draw"()

    .pcc_begin_return
    .return 1
    .pcc_end_return

END:
    .pcc_begin_return
    .return 0
    .pcc_end_return
.end

=item click( x, y, b )

This method is used to send mouse click events to the smiley button.

Parameters:

=over 4

=item x

The vertical mouse position.

=item y

The horizontal mouse position.

=item b

0 = mouse button not pressed

1 = mouse button pressed

=back

=cut

.sub click method
    .param int x
    .param int y
    .param int b

    if y > 32 goto END

    $I0 = classoffset self, 'Mines::Field'
    
    add $I0, 10
    $P0 = getattribute self, $I0
    $I0 = $P0.'click'( x, y, b, self )
    unless $I0 goto END
    
    $I0 = classoffset self, 'Mines::Field'
    add $I0, 2
    $P1 = getattribute self, $I0
    
    $P0.draw( $P1 )
END:

.end

=item reveal_recursive( x, y, width, height ) B<(internal)>

Reveals the specified field recursivly.

The width and height are the dimensions of the board, they
have to be specified for performance reasons.

=cut

.sub reveal_recursive method
    .param int x
    .param int y
    .param int width
    .param int height
    .local pmc field
    .local int pos

    if x < 0 goto END
    if y < 0 goto END
    if x >= width goto END
    if y >= height goto END
    
    pos = y * width
    pos += x

    $I0 = classoffset self, 'Mines::Field'
    
    # field
    $P0 = getattribute self, $I0
    field = $P0
    
    $I0 = field[pos]
    if $I0 == VAL_FREE goto END
    if $I0 == VAL_UNEXPLORED_NO_MINE goto UNEXPLORED
    if $I0 == VAL_UNEXPLORED_MINE goto UNEXPLORED_MINE
    branch END

UNEXPLORED:
    $I0 = _mines_near( field, x, y, width, height )
    field[pos] = $I0
    if $I0 != 0 goto END

    dec y
    dec x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )

    inc y
    dec x
    dec x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )

    inc y
    dec x
    dec x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )
    inc x
    self.'reveal_recursive'( x, y, width, height )
    branch END

UNEXPLORED_MINE:
    field[pos] = VAL_MINE_EXPLODED
    self.'lost'()

END:
    .pcc_begin_return
    .pcc_end_return
.end

=item lost()

Called if a mine is revealed.
Shows the position of all mines on the field.

=cut

.sub lost method
    .local pmc field
    .local int i
    .local int max
    
    self."setStatus"( STATUS_LOST )

    classoffset $I0, self, "Mines::Field"
    getattribute field, self, $I0

    max = field
    i = 0
LOOP:
    if i >= max goto END
    
    $I1 = field[i]

    if $I1 == VAL_UNEXPLORED_MINE goto MINE
    if $I1 == VAL_UNSURE_MINE goto MINE
    if $I1 == VAL_FLAG_NO_MINE goto NO_MINE
    branch NEXT

MINE:    
    $I1 = VAL_MINE
    branch NEXT

NO_MINE:    
    $I1 = VAL_NO_MINE
    branch NEXT
    
NEXT:
    field[i] = $I1
    inc i
    branch LOOP
END:
.end

=item won()

Called when you have won.

=cut

.sub won method
    self."setStatus"( STATUS_WON )
.end

=item check_end()

Checks if you have won.

=cut

.sub check_end method
    .local pmc field
    
    classoffset $I0, self, "Mines::Field"
    getattribute field, self, $I0
    field = new .Iterator, field
    field = .ITERATE_FROM_START
LOOP:
    unless field goto WON
    
    $I0 = shift field

    if $I0 <= 8 goto LOOP
    
    if $I0 == VAL_MINE goto END
    if $I0 == VAL_MINE_EXPLODED goto END
    if $I0 == VAL_UNSURE_MINE goto END
    if $I0 == VAL_FLAG_NO_MINE goto END
    if $I0 == VAL_UNEXPLORED_MINE goto END

    branch LOOP

WON:
    self."won"()
    .pcc_begin_return
    .return 1
    .pcc_end_return
END:
    .pcc_begin_return
    .return 0
    .pcc_end_return
.end

=item setStatus( newStatus )

Sets a new game status.

=cut

.sub setStatus method
    .param int s
    .local pmc screen
    .local pmc watch
    .local pmc status
    
    classoffset $I0, self, "Mines::Field"

    # screen
    add $I0, 2
    screen = getattribute self, $I0

    # watch
    add $I0, 7
    watch = getattribute self, $I0

    # status
    inc $I0
    status = getattribute self, $I0
    
    if s == STATUS_PLAYING goto OK
    if s == STATUS_CHOOSING goto OK
    # not playing at the moment, stop the watch
    watch.'stop'()
OK:
    # no need to start the watch here

    status = s    
    self."undo_mark"( 1 )
    watch.'draw'( screen )
    
DONE:
.end

=item update_stats()

Counts the unrevealed mines and updates the LCD.

=cut

.sub update_stats method
    .local pmc field
    .local int size
    .local pmc count
    .local pmc mines_lcd
    
    classoffset $I0, self, "Mines::Field"
    getattribute field, self, $I0
    add $I0, 8
    getattribute mines_lcd, self, $I0
    
    size = field
    field = new .Iterator, field
    field = .ITERATE_FROM_START
    count = new .ResizablePMCArray

LOOP:
    unless field goto END
    $I0 = shift field
    $I1 = count[$I0]
    inc $I1
    count[$I0] = $I1
    branch LOOP
END:

    $I0 = count[VAL_UNEXPLORED_MINE]
    $I1 = count[VAL_UNSURE_MINE]
    $I2 = count[VAL_FLAG_NO_MINE]
    $I3 = count[VAL_MINE]
    $I4 = count[VAL_MINE_EXPLODED]
    $I5 = count[VAL_MARK_MINE]
    
    $I0 += $I1
    $I0 -= $I2
    $I0 += $I3
    $I0 += $I4
    $I0 += $I5
    mines_lcd = $I0
.end

=back

=head1 INTERNAL FUNCTIONS

=over 4

=item __onload()

Loads necessary modules and creates the B<Mines::Field> class.
This method is called automatically when this module is loaded.

=cut

.sub __onload :load
    $I0 = find_type "Mines::Field"
    if $I0 > 1 goto END

    .local pmc tmp
    .local pmc size
    .local pmc size_rect
    .local pmc prop
    .local pmc from_rect
    .local pmc image
    .local int rect_type
    .local int surface_type

    load_bytecode "examples/sdl/minesweeper/eventhandler.pir"
    load_bytecode "library/SDL/Button.pir"
    load_bytecode "library/SDL/StopWatch.pir"
    load_bytecode "library/SDL/Image.pir"

    # XXX: remove
    load_bytecode "library/Data/Dumper.pir"

    $P0 = new .String
    $P0 = "examples/sdl/minesweeper/mines.png"
    $I0 = find_type "SDL::Image"    
    image = new $I0, $P0
    store_global "Mines::Field", "field", image

    $P0 = new .String
    $P0 = "examples/sdl/minesweeper/mines_debug.png"
    image = new $I0, $P0
    store_global "Mines::Field", "field_debug", image

    newclass $P0, "Mines::Field"
    addattribute $P0, 'field'
    addattribute $P0, 'cache'
    addattribute $P0, 'screen'
    addattribute $P0, 'width'
    addattribute $P0, 'height'
    addattribute $P0, 'mines'
    addattribute $P0, 'markpos'
    addattribute $P0, 'debug'
    addattribute $P0, 'mines_lcd'
    addattribute $P0, 'watch'
    addattribute $P0, 'status_button'
END:
.end

=item _mines_near( field, x, y, width, height )

Returns the number of mines in the neighbourhood
of the field at the specified location.

The width and height are the dimensions of the board.

=cut

.sub _mines_near
    .param pmc field
    .param int x
    .param int y
    .param int width
    .param int height
    .local int mines
    .local int i
    .local int i1
    .local int i2
    .local int j
    .local int j2
    .local int pos
    
    mines = 0
    
    set i1, x
    dec i1
    set i2, x
    inc i2

    set j, y
    dec j
    set j2, y
    inc j2

LOOPj:
    i = i1
LOOPi:
    if i > i2 goto ENDi
    if j < 0 goto ENDi
    if j >= height goto ENDi
    if i < 0 goto NEXTi
    if i >= width goto NEXTi

    pos = j * width
    pos += i
    
    $I0 = _mine_at( field, pos )
    unless $I0 goto NEXTi
    
    inc mines

NEXTi:
    inc i
    branch LOOPi
ENDi:
    inc j
    if j <= j2 goto LOOPj
    
    .pcc_begin_return
    .return mines
    .pcc_end_return
.end

=item _mine_at( field, pos )

Returns 1 if a mine is in the given field
at the specified position, 0 otherwise.

=cut

.sub _mine_at
    .param pmc field
    .param int pos
    .local int v
    
    v = field[pos]
    if v == VAL_MINE goto MINE
    if v == VAL_MINE_EXPLODED goto MINE
    if v == VAL_FLAG_MINE goto MINE
    if v == VAL_UNSURE_MINE goto MINE
    if v == VAL_UNEXPLORED_MINE goto MINE
    if v == VAL_MARK_MINE goto MINE
    .pcc_begin_return
    .return 0
    .pcc_end_return
MINE:
    .pcc_begin_return
    .return 1
    .pcc_end_return
.end

=item _button_clicked( onField )

Called if you click the smiley button.
It starts a new level.

=cut

.sub _button_clicked
    .param pmc field

    $I0 = time
    field.'newLevel'( $I0 )
    field.'draw'()
.end

=back

=head1 AUTHOR

Jens Rieks E<lt>parrot at jensbeimsurfen dot deE<gt> is the author
and maintainer.
Please send patches and suggestions to the Perl 6 Internals mailing list.

=head1 COPYRIGHT

Copyright (C) 2004, The Perl Foundation.

=cut
