2013/03/05

Bomb Sweeper Game

This is "Minesweeper" so-called.
This is required "bomb11.aiff" file.
/*****************************************************************
// bomb sweeper
//    Copyright (C) 1993,2012 by AIG-SOFT
/*****************************************************************
/* variable(like constant)

font("IPAGothic")
int fzenhan
int WX=64
int WY=width(WX,,fzenhan)
int xw=1
if fzenhan then xw=2

/*****************************************************************

int MX =(WX/2)-2    :/* map max x width (-2 for frame)
int MY =19          :/* map max y heigh
int MXX=5           :/* map min x width
int MYY=4           :/* map min y height

int BOMB='*'                  :/* bomb code:'*'=&h2a =< &h3f
int ERR=9                     :/* Judgment mistake
int BMBIT=bit(7)              :/* bit for should bomb
int CHBIT=bit(6)              :/* unknown bit
int OPBIT=(BMBIT or CHBIT)    :/* bits for open status
int NOPBIT=(not OPBIT)        :/* bits for get character only

/* screen home position
int SX=2    :/* sx>=2 & sx+(MX+1)*2< screen x width
int SY=4    :/* sy>=4 & sy+MY+1    < screen y height

int ESC=&h1B
int CR =&h0d

/*****************************************************************
/* global variable

dim char map( (64/2),19)    :/* current map
dim char map0((64/2),19)    :/* virtual screen

dim int    touchNo(10)      :// Touch area No.
int touchCnt     :// The number of touch area

int wx,wy        :/* map width
int seed,bomb    :/* the number of bomb and should bomb
int all          :/* the number of point on all should open
int ts,dt        :/* start time, elapsed time

/*****************************************************************

int ret
int minbomb,maxbomb
/* set field width and the number of bombs
str widthStr,heightStr,bombStr,defaultStr,messageStr
if isLocalizeJapan() then {
    widthStr ="横幅"
    heightStr="縦幅"
    minbomb=MXX*MYY/8 :/* min 1/8
    maxbomb=wx*wy/2     :/* max 1/2
    bombStr="爆弾数"
    defaultStr="標準"
    messageStr="メッセージ"
} else {
    widthStr ="width "
    heightStr="height"
    minbomb=MXX*MYY/8 :/* min=1/8
    maxbomb=wx*wy/2     :/* max=1/2
    bombStr="bombs"
    defaultStr="default"
    messageStr="message"
}
    print widthStr ;"(";MXX;"~";MX;")";
    dim str menues(3)={"10","20","30"}
    menues(3)=defaultStr
    wx=selectMenu(widthStr,menues):// last item of selectMenu() is special
    if wx=3 then wx=2
    wx=(wx+1)*10
    print wx
//    input wx
    print heightStr;"(";MYY;"~";MY;")";
    menues={"5","10","15","19"}
    repeat
        wy=selectMenu2(heightStr,menues)
    until wy<>-1
    wy=5*(wy+1)
    print wy
//    input wy
    
    if wx<MXX then wx=MXX
    if wx>MX  then wx=MX
    if wy<MYY then wy=MYY
    if wy>MY  then wy=MY
    minbomb=MXX*MYY/8 :/* min=1/8
    maxbomb=wx*wy/2     :/* max=1/2
    print bombStr;"(";minbomb;"~";maxbomb")";
    menues={"50","100","150","200"}
    seed=selectMenuWithMessage(bombStr,messageStr,menues)
    seed=50*(seed+1)
    print seed
//    input seed
    if seed<minbomb then seed=minbomb
    if seed>maxbomb then seed=maxbomb

int sno=a_setPlayData("bomb11.aiff")
a_play(sno)

/* main routine
repeat
    /* initialize random number
    srand2()
    
    /* place bombs
    all=BombSeed(seed)
    bomb=0
    BombCount()
    dt=0:/* elapsed time
    
    /* display initial screen
    InitScreen()

    /* key operation
    ret=CursorMove()
    
    /* end check
    if ret=-2 then break:/* force end
    switch ret
        case -1:/* try again
            MapPrintAll(YES):/* display all
            break
        case 0: /* Game clear
            GameClear()
            break
        case 1: /* Game over
            MapPrintAll(YES):/* display all
            GameOver()
            break
    endswitch

    /* Try again
    locate(20,2)
    if isLocalizeJapan() then {
        print "《もう一度しますか?》";
        setFunctionKey(0,"はい"  ,CR)
        setFunctionKey(1,"いいえ",ESC)
    } else {
        print "<< Try Again ? >>";
        setFunctionKey(0,"YES",CR)
        setFunctionKey(1,"NO" ,ESC)
    }
    displayFunctionKey(YES,0,1)
    repeat
        ret=inkey()
    until ret<>0
    displayFunctionKey(NO,0,1)
    // remove touch area
    // Once release and re-set up. Otherwise, it will continue to overlap area.
    resetTouchArea()
until (ret=ESC)
a_end(sno):// release sound buffer
if isLocalizeJapan() then {
    print "終了"
} else {
    print "end"
}
end

/*****************************************************************
/* Functions
/*****************************************************************

func int CursorMove()
/* cursor move and operation
int x,y,c
int t
    /* initial position
    /* move cursor to no bomb place
    for x=0 to wx-1
        for y=0 to wy-1
            if ((map(x,y) and NOPBIT)<>BOMB) then goto "CM1"
        next
    next
label "CM1"
    ts=time():/* start time
    while YES
        /* reverse display at cursor point
        c=map(x,y)
        tatrb(ATRB_REVERSE)
        locate2(x,y)
        print printChr$(c);
        tatrb(ATRB_NORMAL)
        
        // timer count until key input
//        int cnt=0
        while (not kbhit())
            /* until key input none
            t=time()
            if t-ts>dt then { :/* change second
                dt=dt+1
                PrintTime(dt)
//                beep2(0)
//                print "cnt=";cnt
            }
//            inc(cnt)
        endwhile
        
        /* normal display at cursor point
        locate2(x,y)
        print printChr$(c);
        //
        // key operation
        c=inkey()
        beep2(0)    :// click sound
        switch c
            case &h1b: /* retry
                return(-1)
            
            /* cursor roll at screen edge
            case '2': /* ↓
                if y<wy-1 then y=y+1 else y=0
                break
            case '4': /* ←
                if x>0 then x=x-1 else x=wx-1
                break
            case '6': /* →
                if x<wx-1 then x=x+1 else x=0
                break
            case '8': /* ↑
                if y>0 then y=y-1 else y=wy-1
                break
            
            case '5': /* Check
                CheckMapPoint(x,y)
                MapPrint()
                /* The check should not be open to all
                break
            
            case ' ': /* Open
                if OpenMapPoint(x,y) then return(YES):/* game over
                /* display
                if MapPrint() then return(NO)
                break
        endswitch
    endwhile
    return (YES)
endfunc

/*****************************************************************

func int MapPrint()
/* diaplay map and update virtual screen
/* return:0=It is not already open all , 1=open all
int x,y,c
int all0=0
    for y=0 to wy-1
        for x=0 to wx-1
            c=map(x,y)
            if map0(x,y)<>c then {
                /* update screen
                locate2(x,y)
                print printChr$(c)
                map0(x,y)=c:/* update virtual screen
            }
            /* count open point
            if ((c and OPBIT)=OPBIT) then all0=all0+1
        next
    next
    return(all0=all)
endfunc

/*****************************************************************

func MapPrintAll(mode;int)
/* display map all
/* mode : 0=is still , 1=all open (With a judgment mistake)
int x,y,c
str ls
    for y=0 to wy-1
        ls=""
        for x=0 to wx-1
            c=map(x,y)
            if mode then {
                if (c and OPBIT)=BMBIT then {
                    /* checked with 'bomb is here'
                    /* if there is no bomb then it is doubt
                    if (c and NOPBIT)<>BOMB then c=ERR
                }
                c=(c or OPBIT):/* open
            }
            ls=ls+printChr$(c)
        next
        locate2(0,y)
        print ls
    next
    // color(7)
endfunc

/*****************************************************************

func str printChr$(c;int)
/* display character
/* c : bit6,7 = opened(11)/check mark(10)/bomb mark(01)/close(00)
/*     bit0-5 = map status &h00 - &h3f
str cs
    int cc=(c and OPBIT)
    if cc=0 then {
        /* close
        return ("□")
    }
    if cc=CHBIT then {
        /* CHBIT check marking
        return ("?")
    }
    if cc=BMBIT then {
        /* bomb is here marking
        return ("☆")
    }
    if cc=OPBIT then {
        /* opend
        switch (c and NOPBIT)
            case  0:cs= "・":break
            case  1:cs= "1":break
            case  2:cs= "2":break
            case  3:cs= "3":break
            case  4:cs= "4":break
            case  5:cs= "5":break
            case  6:cs= "6":break
            case  7:cs= "7":break
            case  8:cs= "8":break
            case  9:/* mistake
                cs= "×"
                break
            case '*':/* bomb
                cs= "★"
                break
        endswitch
    }
    return (cs)
endfunc

/*****************************************************************

func locate2(x;int,y;int)
    locate(SX+(x)*xw,SY+y)    :/* *xw for double-width character
endfunc

/*****************************************************************

func WakuPrint(yoko;str,tate;str,kado;str,fall;int)
/* display map frame
int i
    /* horizontal line
    str yokos=""
    for i=0 to wx-1:yokos=yokos+yoko:next
    locate2(0,-1):print yokos
    locate2(0,wy):print yokos

    /* vertical line
    if fall then {
        // erase internal = fast
        str tates=tate+space$(wx*xw)+tate
        for i=0 to wy-1
            locate2(-1,i):print tates;
        next
    } else {
        // redraw border only = slow
        for i=0 to wy-1
            locate2(-1,i):print tate;
            locate2(wx,i):print tate;
        next
    }
    
    /* corner
    locate2(-1,-1):print kado;
    locate2(-1,wy):print kado;
    locate2(wx,-1):print kado;
    locate2(wx,wy):print kado;
endfunc

/*****************************************************************

func InitScreen()
/* display initial screen
    cls()
    WakuPrint("-","|","+",YES)
    MapPrintAll(NO)
    locate(5,0)
    if isLocalizeJapan() then {
        print using "マップ幅:##×##  爆弾数:###/###  時間:#####";wx,wy,bomb,seed,dt
            /*         0         1           2         3          4    
            /*        +0123456789012345678901234567890123456789012    
            /*        +locate
    } else {
        print using "map size:##×##  bombs :###/###  time:#####";wx,wy,bomb,seed,dt
    }
    str open$,exit$
    if isLocalizeJapan() then {
        open$="開く"
        exit$="中断"
    } else {
        open$="open"
        exit$="exit"
    }
    int x=WX/2-18
    int y=SY+wy+2
                    //     012345678901234567890123456789
    locate(x,y+0):print "      ┏━┓"
    locate(x,y+1):print "      ┃↑┃"
    locate(x,y+2):print "      ┗━┛"
    locate(x,y+3):print "┏━┓┏━┓┏━┓    ┏━━┓"
    locate(x,y+4):print "┃←┃┃?┃┃→┃    ┃";open$;"┃"
    locate(x,y+5):print "┗━┛┗━┛┗━┛    ┗━━┛"
    locate(x,y+6):print "      ┏━┓"
    locate(x,y+7):print "      ┃↓┃"
    locate(x,y+8):print "      ┗━┛"
    
    int i=0
    touchNo(inc(i))=setTouchAreaWithText(x+ 6,y  ,xw*3,3,'8',YES,125,0,5,100)
    touchNo(inc(i))=setTouchAreaWithText(x+ 6,y+6,xw*3,3,'2',YES,125,0,5,100)
    touchNo(inc(i))=setTouchAreaWithText(x   ,y+3,xw*3,3,'4',YES,125,0,5,100)
    touchNo(inc(i))=setTouchAreaWithText(x+12,y+3,xw*3,3,'6',YES,125,0,5,100)
    //
    touchNo(inc(i))=setTouchAreaWithText(x+ 6,y+3,xw*3,3,'5',YES,150,50, 5,120):/* check
    touchNo(inc(i))=setTouchAreaWithText(x+22,y+3,xw*4,3,' ',YES,150, 5 ,5,120):/* open
    touchCnt=i
    //
    setFunctionKey(0,exit$,ESC)
    displayFunctionKey(YES,0,0)
endfunc

func resetTouchArea()
int i
    for i=0 to touchCnt
        removeTouchArea(touchNo(i))
    next
    touchCnt=0
endfunc

/*****************************************************************

func PrintBombCount()
/* display left bombs
    locate(5+26,0)
    print using "###";bomb
endfunc

/*****************************************************************

func PrintTime(dt;int)
/* display time
    locate(5+42,0)
    print using "#####";dt
endfunc

/*****************************************************************

func GameClear()
/* display game clear screen
    /* change frame design
    beep()
    WakuPrint("◇","◇","◇",NO)
    beep()
    locate(6,1)
    if isLocalizeJapan() then {
        print "§§ おめでとう! あなたは総ての爆弾を捜し当てました §§";
    } else {
        print "<< Congratulations! You've turned up the bomb of all >>";
    }
endfunc

/*****************************************************************

func GameOver()
/* display game over screen
    /* change frame design
    a_play(sno)
    WakuPrint("☆","☆","☆",NO)
    a_play(sno)
    locate(10,1)
    if isLocalizeJapan() then {
        print "@@ あなたは爆弾にぶち当たってしまいました @@";
    } else {
        print "@@ You've hit a bomb @@";
    }
endfunc

/*****************************************************************

func CheckMapPoint(x;int,y;int)
/* check point on the map
int c
    c=map(x,y)
    c=(c and OPBIT)
    if c=OPBIT then {
        /* already open
        /* Reopen the place is open waste
        beep()
        return()
    }
    if c=0 then {
        /* closed -> probable bomb
        map(x,y)=(BMBIT or map(x,y))
        bomb=bomb+1
        PrintBombCount()
        return()
    }
    if c=BMBIT then {
        /* probable bomb -> check please
        map(x,y)=(c and NOPBIT)or CHBIT
        return()
    }
    if c=CHBIT then {
        /* please check -> close
        map(x,y)=(NOPBIT and map(x,y))
        bomb=bomb-1
        PrintBombCount()
    }
endfunc

/*****************************************************************

func int OpenMapPoint(x;int,y;int)
/* open point on the map
int c
    c=map(x,y)
    if ((c and OPBIT)=OPBIT) then {
        /* already open
        /* Reopen the place is open waste
        beep()
        return(NO):/* nothing to do without warning
    }
    if ((c and NOPBIT)=BOMB) then {
        /* open bomb
        a_play(sno)
        return(YES):/* game over
    }
    /* There is open so it is not already open
    if (c=0) then {
        /* If there is no bomb around open in the paint type
        PaintMap(x,y)
    } else {
        /* When there is at least one bomb around, the only one open point
        map(x,y)=(OPBIT or map(x,y)):/* opened symbol
    }
    return(NO)
endfunc

/*****************************************************************

func PaintMap(x;int,y;int)
/* open 0 point from map (x,y)
/* Basically it is same as the paint routine, but it is different to open border
int c,xs,xe
    if map(x,y)<>0 then {
        /* if the first point is not zero then end
        return()
    }
    /* 0 <- x : left search
    xe=x+1 :/* point that is search start right
    while x>=0
        c=map(x,y)
        if ((c and OPBIT)=0) then {
            map(x,y)=(OPBIT or map(x,y))
        }
        if (c<>0) then break:/* border
        /* open border too
        // Border is not bomb.
        // Bacause there are from 1 to 8 around the bomb always.
        x=x-1:/* to left
    endwhile
    if x<0 then xs=0 else xs=x
    /* xs=Leftmost segment(include with border)

    /* x -> wx-1 : right search
    while xe<=wx-1
        c=map(xe,y)
        if (c and OPBIT)=0 then map(xe,y)=(OPBIT or map(xe,y))
        if c<>0 then break:/* order
        xe=xe+1 :/* to right
    endwhile
    if xe=wx then xe=xe-1
    /* xe=rightmost segment(include with border)
    if y>0    then PaintMapSub(xs,xe,y-1):/* upper check
    if y<wy-1 then PaintMapSub(xs,xe,y+1):/* lower check
endfunc

/*****************************************************************

func PaintMapSub(xs;int,xe;int,yy;int)
/* PaintMap() subroutine : for upper/lower check
int x,c
    for x=xs to xe
        c=map(x,yy)
        if c=0 then {
            PaintMap(x,yy)
        } else {
            if (c and OPBIT)=0 then map(x,yy)=(OPBIT or map(x,yy)):/* open with border
        }
    next
endfunc

/*****************************************************************

func int BombSeed(seeds;int)
/* bomb placement in the map
/* seeds : the number of bomb < wx*wy
/* random initialize outside
int x,y
int all
    /* map clear
    for y=0 to wy-1
        for x=0 to wx-1
            map(x,y)=0
        next
    next
    
    /* Number must be open to all non-bomb
    all=wx*wy-seeds
    
    /* bomb placement
    while seeds>0
        x=rand2(wx)
        y=rand2(wy)
        if map(x,y)=0 then {
            /* Set bombs
             map(x,y)=BOMB:/* map
            map0(x,y)=BOMB:/* virtual screen
            seeds=seeds-1 :/* decrement left bomb
        }:/* When there is a bomb there already will look for another location
    endwhile
    
    return(all)
endfunc

/*****************************************************************

func BombCount()
/* Write bomb status in the map
/* Writing in advance the number of bomb around each point
int x,y,xx,yy,xs,ys,xe,ye,c
    for y=0 to wy-1
        ys=y-1:if ys<0    then ys=0
        ye=y+1:if ye>wy-1 then ye=wy-1
        for x=0 to wx-1
            if map(x,y)=BOMB then continue:/* skip bomb
            xs=x-1:if xs<0    then xs=0
            xe=x+1:if xe>wx-1 then xe=wx-1
            /* count around
            c=0
            for yy=ys to ye
                for xx=xs to xe
                    if map(xx,yy)=BOMB then c=c+1
                next
            next
            /* c=0~8
             map(x,y)=c:/* map
            map0(x,y)=c:/* virtual screen
        next
    next
endfunc

/*****************************************************************
/* General functions
/*****************************************************************

func srand2()
/* initialize rand()
int tm=time()
    tm=tm and &h0fff
    tm=tm * 16
    srand(tm)
endfunc

func rand2(seed;int)
    return (rand() mod seed):/* generate random number 0 to seed-1
endfunc

/*****************************************************************
Zip file including sound file is here : XBbs.zip

No comments:

Post a Comment