[Prev] [Home] [Next]
2001/12
13日
本日はオールクリアーの処理(暫定)を行う。
いままでのd.cをenv.cに変更。関数名も変える予定だが、まだ変更はしない。
また、キー値の渡し用にenv.hを作成。使用するのは、input.cのIgetkeyのみとなるので、input.cでもincludeを行う。
---ソース1(ファイル名:env.c)
/*******************************
SOKOBAN for DOS
Env.c
Build:0003
Berse
(C)Thinking Rabbit
*******************************/
#include<dos.h>
#include"env.h"
#define VIDEOBIOS 0x10
#define KEYBIOS 0x16
#define GETKEY 0x10
#define X_0 (-2)
#define Y_0 (-2)
union REGS ireg,oreg;
/*-------------- 20011213-Berse */
int DIgetkey()
{
unsigned char pri,sec;
do{
ireg.h.ah=GETKEY;
int86(KEYBIOS,&ireg,&oreg);
pri = oreg.h.al;
sec = oreg.h.ah;
}while((pri==0)&&(sec==0x03)); /* no key */
if((pri==0x00)||(pri==0xE0)||(pri==0xF0)){
switch(sec){
case 0x48: return(EI_KEY_UP);
case 0x50: return(EI_KEY_DOWN);
case 0x4B: return(EI_KEY_LEFT);
case 0x4D: return(EI_KEY_RIGHT);
default: return(EI_KEY_NO);
}
}else if(pri==0x1b){
return(EI_KEY_ESCAPE); /*escape*/
}else if((pri==0x20)&&(sec==0x39)){
return(EI_KEY_SPACE); /*space*/
}else{
return(EI_KEY_NO);
}
}
DOlocate(c,r)
int r,c;
{
ireg.h.ah=0x02;
ireg.h.bh=0x00;
ireg.h.dh=r+Y_0;
ireg.h.dl=c+X_0;
int86(VIDEOBIOS,&ireg,&oreg);
}
---ソース2(ファイル名:env.h)
#define EI_KEY_NO 0
#define EI_KEY_UP 1
#define EI_KEY_RIGHT 2
#define EI_KEY_DOWN 3
#define EI_KEY_LEFT 4
#define EI_KEY_SPACE 5
#define EI_KEY_ESCAPE 6
---ソース3(ファイル名:input.c)
/*******************************
SOKOBAN for DOS
Input.c
Build:0002
Berse
(c) ThinkingRabbit
*******************************/
#include"input.h"
#include"env.h"
/*-------------- 20011213-Berse */
int Igetkey()
{
char key;
key = DIgetkey();
switch(key){
case EI_KEY_SPACE: return(KEY_A);
case EI_KEY_ESCAPE: return(KEY_B);
case EI_KEY_UP: return(KEY_U);
case EI_KEY_RIGHT: return(KEY_R);
case EI_KEY_LEFT: return(KEY_L);
case EI_KEY_DOWN: return(KEY_D);
default: return(KEY_NO);
}
}
---
levelset.cにて、最大level数とsteplimitを設定するはずがしていなかった(汗)
とりあえず最大level数は2に設定。(同じ面を2度行う事になるが・・・)
steplimitは暫定で9999とした。
---ソース4(ファイル名:levelset.c)
/*******************************
SOKOBAN for DOS
levelset.c
Build:0003
Berse
(c) ThinkingRabbit
*******************************/
#include"level.h"
/* levelset stock */
char Llevelset[][500];
int Lmaxlevel;
/*-------------- 20011213-Berse */
int Lsetlevelset()
{
Lmaxlevel = 2;
return(Lmaxlevel);
}
/*-------------- 20011213-Berse */
Lgetleveldata(retldata)
struct leveldata *retldata;
{
int i,x,y,xstart,ystart,xmax,ymax;
char *ldataline;
struct leveldata ldata;
/* test data */
char *testdata[36];
int xmaxtest,ymaxtest;
testdata[0]= "111111111111111111111111";
testdata[1]= "100330002002000400000001";
testdata[2]= "102020000000000000000001";
testdata[3]= "100000000333300500000001";
testdata[4]= "102020000000000000000001";
testdata[5]= "100330002000200400000001";
testdata[6]= "111111111111111111111111";
testdata[7]= "/";
ymaxtest = 7;
xmaxtest = 24;
/* initialize retldata.block */
for(x=0;x<36;x++){
(*retldata).block[ 0][x] = 1;
(*retldata).block[27][x] = 1;
}
for(y=1;y<27;y++){
(*retldata).block[y][ 0] = 1;
(*retldata).block[y][35] = 1;
}
for(y=1;y<27;y++){
for(x=1;x<35;x++){
(*retldata).block[y][x] = 0;
}
}
(*retldata).steplimit = 9999;
/* testdata -> retldata.block */
ymax = ymaxtest;
xmax = xmaxtest;
ystart = (24-ymax)/2+2;
xstart = (32-xmax)/2+2;
for(y=0;y < ymax;y++){
for(x=0;x < xmax;x++){
(*retldata).block[(ystart+y)][(xstart+ x)]
= testdata[y][x]-'0';
}
}
}
---
そして、sokoban.cにて、最大level数までクリア(つまりオールクリア)すると、オールクリアメッセージを表示する様にする。
また、クリアできてない場合は、とりあえず同じlevelを再度行う事となる。
---ソース5(ファイル名:play.c)
/*******************************
SOKOBAN for DOS
Ver. 0.1 Build:0014
Berse
(C)ThinkingRabbit
*******************************/
#include"level.h"
#define M_TITLE_START 0
#define M_TITLE_EXIT 1
#define P_CLEAR 0
#define P_EXIT 1
#define P_CHANGE_LEVEL 2
char *ver="0.1";
int bld=14;
/*-------------- 20011213-Berse */
int Splaygame(maxlevel)
int maxlevel;
{
int play,level;
struct leveldata ldata;
level = 1;
for(;;){
Lgetleveldata(&ldata);
ldata.steplimit = 9999;
Odispstatus(maxlevel,ldata.steplimit);
play = Pplaylevel(ldata);
if(play==P_CLEAR){
level++;
Oputstr(13,12,"+--------+");
Oputstr(13,13,"+ CLEAR! +");
Oputstr(13,14,"+--------+");
if(level > maxlevel){
Oputstr(13,10,"+--------+");
Oputstr(13,11,"+ ALL +");
Igetkey();
break;
}
Igetkey();
}
}
}
/*-------------- 20011213-Berse */
main()
{
int menu,maxlevel;
maxlevel = Lsetlevelset();
for(;;){
menu = Mtitle(ver,bld);
if(menu == M_TITLE_START){
Splaygame(maxlevel);
}else{
break;
}
}
}
---
あと、menu.cの未使用関数Mplayで使用していたDIgetleyをIgetkeyに変更。しかし良く見るとこの関数まともな値を返さないな・・・。まぁいい。使うときに見直そう。
---ソース6(一部のみ)(ファイル名:menu.c)
/*-------------- 20011213-Berse */
int Mplay()
{
char x,y,bx,by,item,ynow,key;
int i;
Oputstr(38,10,"+------------------+");
Oputstr(38,11,"| Undo |");
Oputstr(38,12,"| Redo |");
Oputstr(38,13,"| Auto Move |");
Oputstr(38,14,"| Trace-mode |");
Oputstr(38,15,"| Retry |");
Oputstr(38,16,"| Change Level |");
Oputstr(38,17,"| Back Title |");
Oputstr(38,18,"| continue Play |");
Oputstr(38,19,"+------------------+");
x=40;y=11;
item=8;
ynow=0;bx=x;by=y+1;
Oputmenucursor(x,y,bx,by);
key=KEY_NO;
while((key==KEY_A)||(key==KEY_B)){
key = Igetkey();
if((key==KEY_U)&&(ynow>0)){
by=y;y--;
Oputmenucursor(x,y,bx,by);
}
if((key==KEY_D)&&(ynow<(item-1))){
by=y;y++;
Oputmenucursor(x,y,bx,by);
}
}
for(i=0;i<(item+2);i++){
Oputstr(38,10+i," ");
}
if(key==KEY_A) return(ynow+1);
if(key==KEY_B) return(0);
}
---
それでは本日のコンパイル。 おっけー。 実行。 おっけー!
ちなみに本日から進み具合をトップページに表示する様にしてみた。
ver.0.2にするまでには、levelをちゃんと2つできる事が残り。もうちょいかかるか。
それと、一部方針転換。d.cをenv.cにしたのもその一部だが、5層構造で作る事とした。
メモ的に書くと、機種環境/部品/デザイン/ロジック/コントロール。
15日
本日は現在のレベル数の表示と、ゲームキャンセルの処理を行う。
まずは現在のレベル数を表示させる様にする。
output.cのOdispstatusからOdisplevelnumを呼び出す。その為に引数levelを追加。
---ソース1(一部)(ファイル名:output.c)
/*-------------- 20011215-Berse */
Odispstatus(level,maxlevel,maxstep)
int level,maxlevel,maxstep;
{
Oputstr(34,10,"LEVEL: /");
Odisplevelnum(level);
Odispmaxlevelnum(maxlevel);
Oputstr(34,12," STEP: /");
Odispmaxstep(maxstep);
}
---
それにともない、呼び出し側(sokoban.c)でもlevelをセット。
また、キャンセル処理の(P_EXITが返る)時タイトルに戻るようにした。
なお、play.cではESCAPEキーが押されたときにP_EXITが返るようにした。
---ソース2(ファイル名:sokoban.c)
/*******************************
SOKOBAN for DOS
Ver. 0.1 Build:0015
Berse
(C)ThinkingRabbit
*******************************/
#include"level.h"
#define M_TITLE_START 0
#define M_TITLE_EXIT 1
#define P_CLEAR 0
#define P_EXIT 1
#define P_RETRY 2
#define P_CHANGE_LEVEL 3
char *ver="0.1";
int bld=15;
/*-------------- 20011214-Berse */
int Splaygame()
{
int play,level, maxlevel;
struct leveldata ldata;
level = 1;
maxlevel = Lgetmaxlevel();
for(;;){
Lgetleveldata(level,&ldata);
Odispstatus(level, maxlevel, ldata.steplimit);
play = Pplaylevel(ldata);
if(play==P_CLEAR){
level++;
Oputstr(13,12,"+--------+");
Oputstr(13,13,"+ CLEAR! +");
Oputstr(13,14,"+--------+");
if(level > maxlevel){
Oputstr(13,10,"+--------+");
Oputstr(13,11,"+ ALL +");
Igetkey();
break;
}
Igetkey();
}else if(play==P_EXIT) break;
}
}
/*-------------- 20011214-Berse */
main()
{
int menu;
Lsetlevelset();
for(;;){
menu = Mtitle(ver,bld);
if(menu == M_TITLE_START){
Splaygame();
}else{
break;
}
}
}
---ソース3(ファイル名:plya.c)
/*******************************
SOKOBAN for DOS
Play.c
Build:0005
Berse
(c) ThinkingRabbit
*******************************/
#include"level.h"
#include"input.h"
#define DIR_U 0
#define DIR_R 1
#define DIR_D 2
#define DIR_L 3
#define MOVE_NG 0
#define MOVE_OK 1
#define MOVE_CLEAR 2
#define P_CLEAR 0
#define P_EXIT 1
#define P_RETRY 2
#define P_CHANGE_LEVEL 3
struct leveldata ldata;
int rest,step,stepmax,push;
char x,y,clear;
Psetlevel()
{
int i,j;
step=0;
push=0;
clear=0;
stepmax=0;
rest=0;
for(i=0;i<28;i++){
for(j=0;j<36;j++){
if((ldata.block[i][j]==5)
||(ldata.block[i][j]==6)){
x=j;y=i;
}
if(ldata.block[i][j]==2){
rest++;
}
}
}
}
Pdomove(xx,yy)
char xx,yy;
{
if(ldata.block[y][x]==5){
ldata.block[y][x]=0;
}else{
ldata.block[y][x]=3;
}
if(ldata.block[yy][xx]==3){
ldata.block[yy][xx]=6;
}else{
ldata.block[yy][xx]=5;
}
Oputblk(xx,yy,ldata.block[yy][xx]);
Oputblk(x,y,ldata.block[y][x]);
x=xx;y=yy;
step++;
Odispstep(step);
if(step>stepmax) stepmax=step;
}
Pdopush(xx,yy,xxx,yyy)
char xx,yy,xxx,yyy;
{
if(ldata.block[yy][xx]==2){
ldata.block[yy][xx]=0;
}else{
ldata.block[yy][xx]=3;
rest++;
clear=0;
}
if(ldata.block[yyy][xxx]==3){
ldata.block[yyy][xxx]=4;
rest--;
if(rest==0)clear=1;
}else{
ldata.block[yyy][xxx]=2;
}
Oputblk(xxx,yyy,ldata.block[yyy][xxx]);
Pdomove(xx,yy);
push++;
}
/*-------------- 20011210-Berse */
int Pmove(dir)
char dir;
{
char xx,yy,xxx,yyy;
if(step >= ldata.steplimit) return(MOVE_NG);
xx=x;yy=y;xxx=x;yyy=y;
switch(dir){
case DIR_U:yy=y-1;yyy=y-2;break; /* up */
case DIR_R:xx=x+1;xxx=x+2;break; /* right */
case DIR_D:yy=y+1;yyy=y+2;break; /* down */
case DIR_L:xx=x-1;xxx=x-2;break; /* left */
default: return(MOVE_NG);
}
switch(ldata.block[yy][xx]){
case 1: /* wall*/
return(MOVE_NG);
case 2:
case 4: /* block */
if((ldata.block[yyy][xxx]==1)
||(ldata.block[yyy][xxx]==2)
||(ldata.block[yyy][xxx]==4)){
return(MOVE_NG);
}else{
/* push ok */
Pdopush(xx,yy,xxx,yyy);
if(clear==1){
return(MOVE_CLEAR);
}else{
return(MOVE_OK);
}
}
default: /* move ok */
Pdomove(xx,yy);
return(MOVE_OK);
}
}
/*-------------- 20011215-Berse */
int Pplaylevel(ldatawk)
struct leveldata ldatawk;
{
char key;
ldata = ldatawk;
Psetlevel();
Odisplevel(ldata);
key = KEY_NO;
for(;;){
key = Igetkey();
switch(key){
case KEY_U: Pmove(DIR_U);break;
case KEY_R: Pmove(DIR_R);break;
case KEY_D: Pmove(DIR_D);break;
case KEY_L: Pmove(DIR_L);break;
}
if(clear==1) break;
if((key==KEY_A)||(key==KEY_B)) break;
}
if(clear == 1) return(P_CLEAR);
if(key==KEY_A) return(P_RETRY);
if(key==KEY_B) return(P_EXIT);
}
---
あと、levelset.cにて、最大レベル数を取得する関数の設置と、データ内に最大ステップ数を持たせる為の修正を行った。
---ソース4(ファイル名:levelset.c)
/*******************************
SOKOBAN for DOS
levelset.c
Build:0004
Berse
(c) ThinkingRabbit
*******************************/
#include"level.h"
/* levelset stock */
int Llevelptr[500];
int Lmaxlevel;
/*-------------- 20011214-Berse */
int Lgetmaxlevel()
{
return(Lmaxlevel);
}
/*-------------- 20011214-Berse */
int Lsetlevelset()
{
Lmaxlevel = 2;
Llevelptr[0] = 0;
Llevelptr[1] = 0;
return(1);
}
/*-------------- 20011214-Berse */
int Lreadsteplimit(line)
char *line; /* line: "/(steplimit)/(level number)"
steplimit: 1-9999 */
{
int i,steplimit;
steplimit = 0;
for(i=1; ((line[i]!='/')&&(i<5)); i++){
steplimit = steplimit * 10
+ (line[i] - '0');
}
return(steplimit);
}
/*-------------- 20011214-Berse */
Lgetleveldata(level,retldata)
int level;
struct leveldata *retldata;
{
int i,x,y,xstart,ystart,xmax,ymax;
char *ldataline;
struct leveldata ldata;
/* test data */
char *testdata[36];
int xmaxtest,ymaxtest;
testdata[0]= "/1000/001";
testdata[1]= "111111111111111111111111";
testdata[2]= "100330002002000400000001";
testdata[3]= "102020000000000000000001";
testdata[4]= "100000000333300500000001";
testdata[5]= "102020000000000000000001";
testdata[6]= "100330002000200400000001";
testdata[7]= "111111111111111111111111";
testdata[8]= "/";
ymaxtest = 7;
xmaxtest = 24;
/* initialize retldata.block */
for(x=0;x<36;x++){
(*retldata).block[ 0][x] = 1;
(*retldata).block[27][x] = 1;
}
for(y=1;y<27;y++){
(*retldata).block[y][ 0] = 1;
(*retldata).block[y][35] = 1;
}
for(y=1;y<27;y++){
for(x=1;x<35;x++){
(*retldata).block[y][x] = 0;
}
}
(*retldata).steplimit = Lreadsteplimit(testdata[0]);
/* testdata -> retldata.block */
ymax = ymaxtest;
xmax = xmaxtest;
ystart = (24-ymax)/2+2;
xstart = (32-xmax)/2+2;
for(y=0;y < ymax;y++){
for(x=0;x < xmax;x++){
(*retldata).block[(ystart+y)][(xstart+ x)]
= testdata[y+Llevelptr[level-1]+1][x]-'0';
}
}
}
---
それでは本日のコンパイル。 おっけー。 実行。 おっけー!
21日
本日は複数レベル対応を行う。対象はlevelset.cのみ。詳細はソース参照。一週間もかけて修正したので、かなり変わっている。しかしコンパイルせずの修正なので、とんでもない間違いがあるかもしれず。
ポイントは、__testdataをメンバ変数とし、その一次元目のインデックスとしてtestptrを設置。
データの取得は__testdataからtestptrを用いて行う事とする。
これにより、testptrを各レベルデータの先頭に指定することで、レベルデータのランダムアクセスが可能となる。(一時的。__testdata自体は将来なくなる予定)
各レベルの先頭は_Llevelptrにて保持しておく。今回2レベル目を作成(非常に簡単だが)し、1レベル目/2レベル目の__testdataの先頭番号([]内の数値)をそれぞれ_Llevelptrにセットしている。(Lsetlevelset)
また、変数名に以下のルールを適用する事とした。まだこのソースリストのみなので、順次他のソースにも展開していく。
・ポインタ/配列には頭に_を付ける
(ポインタ&配列または多次元配列の場合はその数だけ付ける)
・1からカウントする変数は最後にLを付ける
---ソース1(ファイル名:levelset.c)
/*******************************
SOKOBAN for DOS
levelset.c
Build:0005
Berse
(c) ThinkingRabbit
*******************************/
/*========== define section */
#include"level.h"
#define RIGHT_LIMIT 36
#define BOTTOM_LIMIT 28
/* levelset stock */
int _Llevelptr[500];
int LmaxlevelN;
char *__testdata[36]; /*TEST*/
int testptr;
/*========== initialize section */
/*-------------- 20011220-Berse */
int Lsetlevelset()
{
/*TEST - */
__testdata[0]= "/1000/001";
__testdata[1]= "111111111111111111111111";
__testdata[2]= "100330002002000400000001";
__testdata[3]= "102020000000000000000001";
__testdata[4]= "100000000333300500000001";
__testdata[5]= "102020000000000000000001";
__testdata[6]= "100330002000200400000001";
__testdata[7]= "111111111111111111111111";
__testdata[8]= "/100/002";
__testdata[9]= "1111111";
__testdata[10]= "1302051";
__testdata[11]= "1111111";
__testdata[12]= "/";
testptr=0;
/* - TEST*/
_Llevelptr[0] = 0;
_Llevelptr[1] = 8;
LmaxlevelN = 2;
return(1);
}
/*========== level data set section */
/*-------------- 20011221-Berse */
Lreadyread(levelN)
int levelN;
{
testptr = _Llevelptr[levelN-1];
}
/*-------------- 20011221-Berse */
char *Lreadleveldata()
{
char *_line;
_line=__testdata[testptr];
testptr++;
return(_line);
}
/*-------------- 20011220-Berse */
int Lreadsteplimit()
{
int i,steplimit;
char *_line; /* line: "/(steplimit)/(level number)"
steplimit: 1-9999 */
_line = Lreadleveldata();
steplimit = 0;
for(i=1; ((_line[i]!='/')&&(i<5)); i++){
steplimit = steplimit * 10 + (_line[i] - '0');
}
return(steplimit);
}
/*-------------- 20011221-Berse */
Lsettemplevel(levelN,_ldata,_ymax,_xmax)
struct leveldata *_ldata;
int levelN,*_ymax,*_xmax;
{
int y,x;
char *_line;
Lreadyread(levelN);
(*_ldata).steplimit = Lreadsteplimit();
*_xmax=0;
for(y=0;;y++){
_line = Lreadleveldata();
/*BRK*/ if(_line[0]=='/') break; /* next level data's line*/
for(x=0;x*_xmax) *_xmax=x;
}
*_ymax=y;
}
/*-------------- 20011218-Berse */
Linitretldata(_retldata)
struct leveldata *_retldata;
{
int x,y;
/* initialize retldata.block */
for(x=0;x < RIGHT_LIMIT;x++){
(*_retldata).block[ 0][x] = 1;
(*_retldata).block[BOTTOM_LIMIT-1][x] = 1;
}
for(y=1;y < BOTTOM_LIMIT-1;y++){
(*_retldata).block[y][ 0] = 1;
(*_retldata).block[y][RIGHT_LIMIT-1] = 1;
for(x=1;x < RIGHT_LIMIT-1;x++){
(*_retldata).block[y][x] = 0;
}
}
}
/*-------------- 20011221-Berse */
Lcopytemp(templdata,ymax,xmax,_retldata);
int ymax,xmax;
struct leveldata templdata, *_retldata;
{
(*_retldata).steplimit = templdata.steplimit;
ystart = (BOTTOM_LIMIT-ymax)/2+2;
xstart = (RIGHT_LIMIT -xmax)/2+2;
for(y=0;y < ymax;y++){
for(x=0;x < xmax;x++){
(*_retldata).block[(ystart +y)][(xstart +x)]
= templdata.block[y][x];
}
}
}
/*========== get method section */
/*-------------- 20011221-Berse */
Lgetleveldata(levelN,_retldata)
int levelN;
struct leveldata *_retldata;
{
int x,y,xstart,ystart,xmax,ymax;
struct leveldata templdata;
Lsettemplevel(levelN,&templdata,&ymax,&xmax);
Linitretldata(_retldata);
Lcopytemp(templdata,ymax,xmax,_retldata);
}
/*-------------- 20011214-Berse */
int Lgetmaxlevel()
{
return(LmaxlevelN);
}
---
それでは一週間分の思いをこめて、今、コンパイル!
よし、エラー!(「よし」ではないな)
Lcopytempの宣言部にせみころん君が・・・。
[Prev] [Home] [Next]