#99 Article 182 Posted at 1992/02/18 22:58:48 by 相友優 (MAP268) [PAINT]

Subject: Re:*8 領域ペイント /176 .... /167 /164

そんじゃ、昔仕事用に空で書いた奴(タイルに対応してる奴)を忘れないように(笑)
 あげときます。

 以下( Turbo pascal 5.0 以上で 98互換機ね )

 まず単色塗り

program paint;

type istr=string[80];

function value(i:istr):longint;
var n:longint; n1:word;
begin
  while (copy(i,1,1)=' ') or (copy(i,1,1)='+') do delete(i,1,1);
  val(i,n,n1);
  if n1<>0 then begin
    i:=copy(i,1,n1-1);
    val(i,n,n1)
  end;
  value:=n;
  if i='' then value:=0;
end;

function cstr(i:longint):istr;
var c : istr;

  function cv(n:longint):istr;
  var d:longint; m:word;
  begin
    d:=n div 10; m:=n mod 10;
    if d<>0 then cv:=cv(d)+chr(m+48)
    else
      cv:=chr(m+48);
  end;

begin
   c:='';
   if i<0 then c:='-';
   cstr:=c+cv(abs(i));
end;

const bp:array[0..7] of byte=(128,64,32,16,8,4,2,1);
      maxfifo=4096;

type
     v80=array [0..79] of byte;
     vra=array [0..399] of v80;
     poi=record
		x,y:word;
		dir:boolean;
	end;

var 
     vram0:vra absolute $a800:0;
     vram1:vra absolute $b000:0;
     vram2:vra absolute $b800:0;
     ox,oy:word;
     stack:array [0..maxfifo] of poi;
     fi,fo:word;

procedure pushpo(x,y:word);
begin
	inc(fi);
        fi:=fi mod maxfifo;
	stack[fi].x:=x;
	stack[fi].y:=y;
end;

procedure pulpo(var x,y:word);
begin
  if fi<>fo then begin
	inc(fo);
        fo:=fo mod maxfifo;
	x:=stack[fo].x;
	y:=stack[fo].y;
  end else begin x:=ox; y:=oy; end;
end;

function point(x,y:word):boolean;
var p:word;
begin
  p:=x and 7;
  x:=x shr 3;
  point:=((vram0[y][x] and bp[p])<>0) or
         ((vram1[y][x] and bp[p])<>0);
end;

procedure pset(x,y:word);
var p:word;
begin
  p:=x and 7;
  x:=x shr 3;
  vram0[y][x]:=vram0[y][x] or bp[p];
  vram1[y][x]:=vram1[y][x] or bp[p];
end;

procedure line(x1,x2,y:word);
var i:word;
begin
  for i:=x1 to x2 do pset(i,y);
end;

function seekp(x,y:word; dir:boolean):boolean;
var sp:boolean;
begin
  sp:=false;
  if dir then begin {↓方向}
    if y<399 then sp:=not point(x,y+1);
  end else if y>0 then sp:=not point(x,y-1);
  seekp:=sp;
end;

procedure paintf(x,y:word);
var dir:boolean; dirf,dirb:array [boolean] of boolean; px,x1,x2:word;
const dirc:array[boolean] of integer=(-1,1);
begin
    pushpo(x,y);
    while (fi<>fo) do begin
      pulpo(x,y);
      if not point(x,y) then begin
        x1:=x; x2:=x;
        while (not point(x1,y)) and (x1>1) do dec(x1);
        inc(x1);
        while (not point(x2,y)) and (x2<639) do inc(x2);
        dec(x2);
        line(x1,x2,y);
        dirf[false]:=seekp(x1,y,false); dirf[true]:=seekp(x1,y,true);
        dirb[false]:=false; dirb[true]:=false;
        px:=x1;
        while px<=x2 do begin
          for dir:=false to true do begin
            if (not dirb[dir]) and dirf[dir] then pushpo(px,y+dirc[dir]);
            dirb[dir]:=dirf[dir]; dirf[dir]:=seekp(px,y,dir);
          end;
        inc(px);
        end;
      end;
    end;
end;

begin
  fi:=0; fo:=0;
  if ParamCount>1 then begin
     ox:=value(ParamStr(1));
     oy:=value(ParamStr(2));
	paintf(ox,oy);
  end;
end.

 あ、もしかして塗るところはアルゴリズムのチェック用だったから手を抜いてるかも
 しれない… ま~い~や。 読めばわかるでせう。

 次、たいる。

program paint2;

type istr=string[80];

function value(i:istr):longint;
var n:longint; n1:word;
begin
  while (copy(i,1,1)=' ') or (copy(i,1,1)='+') do delete(i,1,1);
  val(i,n,n1);
  if n1<>0 then begin
    i:=copy(i,1,n1-1);
    val(i,n,n1)
  end;
  value:=n;
  if i='' then value:=0;
end;

function cstr(i:longint):istr;
var c : istr;

  function cv(n:longint):istr;
  var d:longint; m:word;
  begin
    d:=n div 10; m:=n mod 10;
    if d<>0 then cv:=cv(d)+chr(m+48)
    else
      cv:=chr(m+48);
  end;

begin
   c:='';
   if i<0 then c:='-';
   cstr:=c+cv(abs(i));
end;

const
      bp:array[0..7] of byte=(128,64,32,16,8,4,2,1);
      lc:array[0..7] of byte=($ff,$7f,$3f,$1f,$f,$7,$3,$1);
      rc:array[0..7] of byte=($80,$c0,$e0,$f0,$f8,$fc,$fe,$ff);

      maxfifo=8192;

type
     v80=array [0..79] of byte;
     vra=array [0..399] of v80;
     poi=record
		x,y:word;
		dir:boolean;
	end;

var 
     vram0:vra absolute $a800:0;
     vram1:vra absolute $b000:0;
     vram2:vra absolute $b800:0;
     ox,oy,bc:word;
     stack:array [0..maxfifo] of poi;
     fi,fo:word;
     pti:istr;

procedure paintf(x,y,bc:word; tile:istr);
type
      tiles=array[0..2] of byte;
      tilep=array[0..25] of tiles;

var dir:boolean; dirf,dirb:array [boolean] of boolean; px,x1,x2:integer;
    tl:word; ti:tiles; tt:tilep; yy:word; ym:integer;
const dirc:array[boolean] of integer=(-1,1);


procedure pushpo(x,y:word);
begin
	inc(fi);
        fi:=fi mod maxfifo;
	stack[fi].x:=x;
	stack[fi].y:=y;
end;

procedure pulpo(var x,y:word);
begin
  if fi<>fo then begin
	inc(fo);
        fo:=fo mod maxfifo;
	x:=stack[fo].x;
	y:=stack[fo].y;
  end else begin x:=ox; y:=oy; end;
end;

function point(x,y:word):boolean;
var p:word; cl,b,r,g:byte; q:boolean;
begin
  p:=x and 7;
  x:=x shr 3;
  cl:=bp[p];
  b:=vram0[y][x];
  r:=vram1[y][x];
  g:=vram2[y][x];
  case bc of
   0:q:=(not (b or r or g) and cl)<>0;
   1:q:=(b and not (r or g) and cl)<>0;
   2:q:=(r and not (b or g) and cl)<>0;
   3:q:=(b and r and (not g) and cl)<>0;
   4:q:=(g and not (b or r) and cl)<>0;
   5:q:=(b and g and (not r) and cl)<>0;
   6:q:=(r and g and (not b) and cl)<>0;
   7:q:=(b and r and g and cl)<>0;
  end;
  if not q then begin 
        ym:=(y-yy) mod tl;
       q:=(((b and cl)=((tt[ym][0]) and cl)) and
       ((r and cl)=((tt[ym][1]) and cl)) and
       ((g and cl)=((tt[ym][2]) and cl)));
  end;
  point:=q;
end;

procedure pset(x,y:word);
var p:word;
begin
  p:=x and 7;
  x:=x shr 3;
  vram0[y][x]:=vram0[y][x] or bp[p];
end;

procedure tline(x1,x2,y:word; ti:tiles);
var j,i,xx1,xx2,p1,p2:word; cp:byte;

procedure setpt;
begin
  vram0[y][xx1]:=(vram0[y][xx1] and not cp) or (ti[0] and cp);
  vram1[y][xx1]:=(vram1[y][xx1] and not cp) or (ti[1] and cp);
  vram2[y][xx1]:=(vram2[y][xx1] and not cp) or (ti[2] and cp);
  dec(i);
  inc(xx1);
end;

begin
  p1:=x1 and 7;
  p2:=x2 and 7;
  xx1:=x1 shr 3;
  xx2:=x2 shr ;
  i:=xx2-xx1+1;
  if xx2=xx1 then begin cp:=lc[p1] and rc[p2]; setpt; end else
    begin 
    cp:=lc[p1];
    setpt;
    cp:=$ff;
    if i>2 then for j:=1 to i-1 do setpt;
    cp:=rc[p2];
    setpt;
    end;
end;

function seekp(x,y:word; dir:boolean):boolean;
var sp:boolean;
begin
  sp:=false;
  if dir then begin {↓方向}
    if y<399 then sp:=not point(x,y+1);
  end else if y>0 then sp:=not point(x,y-1);
  seekp:=sp;
end;


begin
  tl:=ord(tile[0]) div 3;
  for yy:=0 to tl-1 do begin
    tt[yy][0]:=byte(tile[yy*3+1]);
    tt[yy][1]:=byte(tile[yy*3+2]);
    tt[yy][2]:=byte(tile[yy*3+3]);
  end;
  yy:=y;
    pushpo(x,y);
    while (fi<>fo) do begin
      pulpo(x,y);
      if not point(x,y) then begin
        x1:=x; x2:=x;
        while (not point(x1,y)) and (x1>0) do dec(x1);
        inc(x1);
        while (not point(x2,y)) and (x2<640) do inc(x2);
        dec(x2);
        ym:=(y-yy) mod tl;
        tline(x1,x2,y,tt[ym]);
        dirf[false]:=false; dirf[true]:=false;
        px:=x1;
        while px<=x2 do begin
          for dir:=false to true do begin
            dirb[dir]:=dirf[dir]; dirf[dir]:=seekp(px,y,dir);
            if (not dirb[dir]) and dirf[dir] then pushpo(px,y+dirc[dir]);
          end;
        inc(px);
        end;
      end;
    end;
end;

{
	00000000
	00110110
	01111111
	01111111
	00111110
	00011100
	00001000
	00000000
	00000000
}


begin
  fi:=0; fo:=0; pti:=#$0#$FF#$AA#0#$FF#$55;
{  fi:=0; fo:=0; pti:=#$55#$ff#$55#$aa#$ff#$aa;}
  fi:=0; fo:=0; pti:=#$ff#$ff#$ff#$c9#$ff#$c9#$80#$ff#$80#$80#$ff#$80#$c1#$ff#$c1#$f7#$ff#$f7#$ff#$ff#$ff#$ff#$ff#$ff;
  if ParamCount>2 then begin
     ox:=value(ParamStr(1));
     oy:=value(ParamStr(2));
     bc:=value(ParamStr(3));
	paintf(ox,oy,bc,pti);
  end;
end.


 そ~いうわけで、何かに使えるとは思うけど(そこそこ高速だけど)あんまり奇麗な
 Pascalじゃないなぁ(笑) 結局これは全部アセンブラ化してJ31に某社のグラフィックライブラリに乗ってたりする。ううむ。

 そ~とも