//「Tiny Solitaire」
//アコーディオン(スタンドアロン版)ソースコード
//for HSP3

//戻る



//
// Tiny Solitaire "Accordion"
// 作・六月の玉子
//


//----------------------------------------
//		ここから変更可能な定義
//----------------------------------------

#const bas_size0 0
//↑ウィンドウの横サイズはこの数値×80、縦サイズはこの数値×60になる。
//(たとえば8なら640×480)
//5以下にした場合はディスプレイサイズに合わせて自動設定される。
//画面からはみ出す大きさに設定した場合は、画面からはみ出さない最大サイズに修正される。

#const alpha0 255
//ウィンドウの不透明度。128~255の間で指定。(範囲から外れた場合は範囲内に入るように調整される)
//255の場合は透過なし。

#const mesh 12
//背景をメッシュ透過する時のメッシュの濃度。alpha0が255以上の時のみ有効。
//範囲は0~16で、16の場合は透過なし。

#const save_game 1
//↑これを0にした場合はデータのセーブを行わない。

#define global font_name "Microsoft Sans Serif"
//↑使用するフォント(本ソフトではASCII文字しか使いません)
//OpenTypeもしくはTrueTypeフォントを推奨。

#const font_anl 1
//↑これを0にした場合はフォントの解析を行わない。
//カード画像が上手く表示されない場合は0にしてみてください。


//----------------------------------------
//		ここまで変更可能な定義
//----------------------------------------

#packopt hide 1
#include "user32.as"
#include "gdi32.as"
#module
//コロナ退散のお経をメモリ上にUTF-16形式で置きます(204バイト使用)
//参考 https://blog.goo.ne.jp/mayumiakane1962/e/623f3c74565d3e1ba5951dd8adc34e76
#deffunc kyakuun
	dim kyakuun16,51
	kyakuun16(0) =0x71215357,0x96404ECF,0x00208036,0x71215357
	kyakuun16(4) =0x78E89054,0x00208036,0x71215357,0x4F3D50E7
	kyakuun16(8) =0x00208036,0x71215357,0x65B95341,0x4ECF8AF8
	kyakuun16(12)=0x53570020,0x8AF87121,0x85A983E9,0x8A366469
	kyakuun16(16)=0x002085A9,0x71215357,0x80568AF8,0x002050E7
	kyakuun16(20)=0x71215357,0x5E2B546A,0x6C990020,0x4F497F85
	kyakuun16(24)=0x6C990020,0x4F497F85,0x6C990020,0x4F497F85
	kyakuun16(28)=0x59220020,0x5357591A,0x00209B3C,0x4F49963F
	kyakuun16(32)=0x9B3C5C3C,0x5C3C0020,0x5C384F49,0x00209B3C
	kyakuun16(36)=0x4F49963F,0x9B3C90A3,0x6CE20020,0x5C3C7F85
	kyakuun16(40)=0x00209B3C,0x6BD8963F,0x9B3C7F85,0x6CE20020
	kyakuun16(44)=0x68C363D0,0x00209B3C,0x53BB75BE,0x53BB75BE
	kyakuun16(48)=0x83AB0020,0x4E455F97,0x00004F4F
	//お経の内容を見たい人は下の行のコメントアウトを外してください
	//dim s : MessageBoxW hwnd,varptr(kyakuun16),varptr(s),0
	return
#global
kyakuun

#define global ctype lower(%1,%2) ((%2)+((%1)-(%2))*((%1)<(%2)))	//小さい方を返す(整数)
#define global ctype higher(%1,%2) ((%2)+((%1)-(%2))*((%1)>(%2)))	//大きい方を返す(整数)
#define global boxf2(%1,%2,%3,%4) boxf %1,%2,(%1)+(%3)-1,(%2)+(%4)-1
#define global circle2(%1,%2,%3,%4,%5=1) circle %1,%2,(%1)+(%3),(%2)+(%4),%5
#define global tri_init dim _tri_x,4 : dim _tri_y,4
#define global tri(%1,%2,%3,%4,%5,%6,%7=0) _tri_x=%1,%1,%3,%5 : _tri_y=%2,%2,%4,%6 : gsquare -1-(%7),_tri_x,_tri_y
#define global squ(%1,%2,%3,%4,%5,%6,%7,%8,%9=0) _tri_x=%7,%1,%3,%5 : _tri_y=%8,%2,%4,%6 : gsquare -1-(%9),_tri_x,_tri_y
#define global tri_out dim _tri_x : dim _tri_y
#define global cent(%1,%2,%3,%4,%5) rect=%2,%3,(%2)+(%4),(%3)+(%5) : DrawText hdc,%1,-1,varptr(rect),0x25
#define global oc_dialog(%1="",%2="",%3=0) MessageBox hwnd,%1,%2,0x21|((%3)*0x100)
#const global IDOK 1
#const global IDCANCEL 2

#module
#deffunc r_box int rx,int ry,int rw,int rh,int rr	//角が丸い四角形を描く
	if rr<=0 : boxf2 rx,ry,rw,rh : return
	boxf2 rx+rr,ry,rw-rr*2,rh
	boxf2 rx,ry+rr,rw,rh-rr*2
	circle2 rx,ry,rr*2,rr*2
	circle2 rx+rw-rr*2,ry,rr*2,rr*2
	circle2 rx,ry+rh-rr*2,rr*2,rr*2
	circle2 rx+rw-rr*2,ry+rh-rr*2,rr*2,rr*2
	return

#deffunc rd_start
	rd_flag=0 : redraw 0 : return

#deffunc rd_update int ru1,int ru2,int ru3,int ru4
	if rd_flag {
		xmin=lower(xmin,ru1) : ymin=lower(ymin,ru2)
		xmax=higher(xmax,ru1+ru3) :	ymax=higher(ymax,ru2+ru4)
	} else {
		xmin=ru1 : ymin=ru2
		xmax=ru1+ru3 : ymax=ru2+ru4
		rd_flag=1
	}
	return

#deffunc rd_end
	if rd_flag : redraw 1,xmin,ymin,xmax-xmin,ymax-ymin : else : redraw 3
	return
#global

//タイルパターンで染める
#module
#deffunc tp_fill_init int _tb,local t_gid
	tb=limit(_tb,0) : t_gid=ginfo_sel
	gsel tb : tsw=ginfo_sx : tsh=ginfo_sy : gsel t_gid : return

#deffunc tp_fill int _tx,int _ty,int tw,int th
	if (tsw=0)|(tsh=0) : return
	if (tw<=0)|(th<=0) : return
	tx=limit(_tx,0) : ty=limit(_ty,0)
	tx2=(tx+tw) : ty2=(ty+th)	//右下の座標
	l=tx\tsw : r=tx2\tsw	//左の描画しない範囲と右の描画する範囲
	u=ty\tsh : d=ty2\tsh	//上の描画しない範囲と下の描画する範囲
	tx0=tx/tsw*tsw : ty0=ty/tsh*tsh	//描画の原点
	lp_x=(tx2/tsw)-(tx/tsw)+1 : lp_y=(ty2/tsh)-(ty/tsh)+1	//横方向と縦方向のループ回数
	repeat lp_y
		cnt0=cnt
		u2=u*(cnt=0) : if cnt=lp_y-1 : d2=d-u2 : else : d2=tsh-u2
		if d2<=0 : break 
		repeat lp_x
			l2=l*(cnt=0) : if cnt=lp_x-1 : r2=r-l2 : else : r2=tsw-l2
			if r2<=0 : break
			pos cnt*tsw+tx0+l2,cnt0*tsh+ty0+u2 : gcopy tb,l2,u2,r2,d2
		loop
	loop
	return
#global

#define global ctype bas(%1) ((%1)*bas_size)
#define global bas_half (bas_size/2)
#define global bas_qua (bas_size/4)

#define global black palcolor 0
#define global white palcolor 1
#define global green palcolor 3
#define global yellow palcolor 4
#define global blue palcolor 5
#define global magenta palcolor 6
#define global cyan palcolor 7

#define global buffer2(%1,%2,%3,%4=1) buffer %1,%2,%3,%4 : gsel %1 : mref c_pal,69 : memcpy c_pal,pal_m,768,0,0 : palette ,,,,1
#define global screen2(%1,%2,%3,%4=1) screen %1,%2,%3,%4 : gsel %1 : mref c_pal,69 : memcpy c_pal,pal_m,768,0,0 : palette ,,,,1

#define global ctype suit(%1) ((%1)/13)
#define global ctype rank(%1) ((%1)\13)

//セーブファイル関連
#define fname "acc_save.dat"
#const fsize 24
#define data_reset dim playdata,3,2
goto *_jump1
#deffunc save
	if save_game : bsave fname,playdata,fsize
	return
#deffunc load
	if save_game {
		exist fname : if strsize=-1 : bsave fname,playdata,fsize : else : bload fname,playdata,fsize
	}
	return
*_jump1

//汎用配列
dim rect,4 : dim point,2

//モニター情報の取得
x=0 : dim moninfo,10
rect=ginfo_wx1,ginfo_wy1,ginfo_wx2,ginfo_wy2
MonitorFromRect varptr(rect),2 : h_mon=stat	//MONITOR_DEFAULTTONEAREST=2
if h_mon {
	moninfo(0)=40 : GetMonitorInfo h_mon,varptr(moninfo)
	if stat {
		mon_x=moninfo(5) : mon_y=moninfo(6) : mon_w=moninfo(7)-mon_x : mon_h=moninfo(8)-mon_y
	} else {
		x=1
	}
} else {
	x=1
}
if x : mon_x=0 : mon_y=0 : mon_w=ginfo_dispx : mon_h=ginfo_dispy
dim moninfo : winb_w=ginfo_sizex-ginfo_winx : winb_h=ginfo_sizey-ginfo_winy
//bas_sizeの設定
bas_max=lower((mon_w-winb_w)/80,(mon_h-winb_h)/60)
if bas_size0>5 {
	bas_size=limit(bas_size0,,bas_max)
} else {
	x=(mon_w-winb_w)*4/400 : y=(mon_h-winb_h)*4/300 : bas_size=lower(x,y)	//5*80=400 5*60=300
}

//カード基本情報の設定
c_w=bas(5) : c_h=bas(8)	//カードサイズ
c_r=bas(1) : c_b=bas_half	//カード角の丸み、枠の太さ
suit_w=bas(3) : suit_h=bas(3)	//マークのサイズ
rank_w=bas(3) : rank_h=bas(3)	//文字のサイズ
suit_x=bas(1) : suit_y=bas(1)	//マークの位置
rank_y=bas(4)	//文字の基本位置(X座標はセンタリング表示)
tag_w=c_w/2	//タグの大きさ

//マスターパレットの作成
sdim pal_m,768
dim tmp,57
//黒(0)、白(1)、赤(2)、緑(3)、黄(4)、青(5)、マゼンタ(6)、シアン(7)
tmp(0) =0,0,0, 255,255,255, 255,0,0, 0,255,0, 255,255,0, 0,0,255, 255,0,255, 0,255,255
//スペード背景(8)、文字(9)、クラブ背景(10)、文字(11)、ハート背景(12)、文字(13)、ダイヤ背景(14)、文字(15)
tmp(24)=1,1,1, 255,255,255, 0,240,0, 1,1,1, 240,0,0, 1,1,1, 0,0,240, 255,255,255
//グレー(16,17,18)
tmp(48)=64,64,64, 128,128,128, 230,230,230
repeat 57 : poke pal_m,cnt,tmp(cnt) : loop
dim tmp
//背景透過色(パレット番号100)
//タイトルバーの色(パレット番号101)
//タイトルバーの文字(パレット番号102)
//ウィンドウの背景色(パレット番号103)
x=0x563412 : lpoke pal_m,300,x : syscolor 2 : y=(ginfo_b<<16)|(ginfo_g<<8)|ginfo_r : if x=y : y++
lpoke pal_m,303,y : syscolor 9 : y=(ginfo_b<<16)|(ginfo_g<<8)|ginfo_r : if x=y : y++
lpoke pal_m,306,y : syscolor 5 : y=(ginfo_b<<16)|(ginfo_g<<8)|ginfo_r : if x=y : y++
lpoke pal_m,309,y

//ランク文字
sdim rank_n,3,13
rank_n="A","2","3","4","5","6","7","8","9","10","J","Q","K"

//テキストの文字サイズの設定
font_size=208
repeat 200,9
	font font_name,cnt
	GetTextExtentPoint32 hdc,"W",1,varptr(point)
	if (point(0)>bas(2))|(point(1)>bas(2)) : font_size=cnt : break
loop

//カードの文字サイズの設定
font_size2=208	//カード用フォントのサイズ
dim main_w,14	//文字幅
dim left_w,14	//文字の左スペース
if font_anl {
	//フォントデータの解析
	dim textm,14
	repeat 200,9
		font font_name,cnt
		GetTextMetrics hdc,varptr(textm)
		if textm(0)-textm(3)>rank_h {
			font_size2=cnt
			rank_y+=textm(2)/2-textm(3)	//カードの数字表示位置の補正
			break
		}
	loop
	dim textm : dim abc,102
	font font_name,font_size2
	GetCharABCWidths hdc,48,81,varptr(abc)
	left_w(0)=abc(51),abc(6),abc(9),abc(12),abc(15),abc(18),abc(21)
	left_w(7)=abc(24),abc(27),abc(3),abc(78),abc(99),abc(81),abc(0)
	main_w(0)=abc(52),abc(7),abc(10),abc(13),abc(16),abc(19),abc(22)
	main_w(7)=abc(25),abc(28),abc(4),abc(79),abc(100),abc(82),abc(1)
	dim abc
} else {
	repeat 200,9
		font font_name,cnt
		GetTextExtentPoint32 hdc,"W",1,varptr(point)
		if point(1)>rank_h : font_size2=cnt : break
	loop
	font font_name,font_size2
	repeat 13
		if cnt=9 {
			GetTextExtentPoint32 hdc,"1",1,varptr(point)
			main_w(9)=point(0)
			GetTextExtentPoint32 hdc,"0",1,varptr(point)
			main_w(13)=point(0)
		} else {
			GetTextExtentPoint32 hdc,rank_n(cnt),1,varptr(point)
			main_w(cnt)=point(0)
		}
	loop
}

//カード画像作成
//ベース部分
buffer2 1,c_w*13,c_h*5 : black : boxf
repeat 4
	palcolor 18 : r_box 0,c_h*cnt,c_w,c_h,c_r
	palcolor cnt*2+8 : r_box c_b,c_h*cnt+c_b,c_w-c_b*2,c_h-c_b*2,limit(c_r-c_b,0)
loop
repeat 12,1 : pos c_w*cnt,0 : gcopy 1,0,0,c_w,c_h*4 : loop

//スート部分作成
tri_init : buffer2 2,100,100
//スペード
palcolor 8 : boxf : palcolor 9 : boxf2 0,50,100,50 : palcolor 8
circle2 -50,-50,98,200 : circle2 52,-50,98,200
palcolor 9 : circle2 0,40,50,50 : circle2 50,40,50,50
palcolor 8 : boxf2 0,0,100,48
palcolor 9 : tri 50,0,93,48,8,48,9 : boxf2 10,48,80,30
gsel 1
repeat 13
	pos c_w*cnt+suit_x,c_h*0+suit_y
	gzoom suit_w,suit_h,2,0,0,100,100
loop
//クラブ
gsel 2 : palcolor 10 : boxf : palcolor 11
boxf2 0,50,100,50 : palcolor 10 : circle2 -50,-50,98,200 : circle2 52,-50,98,200
palcolor 11 : circle2 33,38,35,35
circle2 0,40,45,45 : circle2 55,40,45,45 : circle2 30,0,40,45
gsel 1
repeat 13
	pos c_w*cnt+suit_x,c_h*1+suit_y
	gzoom suit_w,suit_h,2,0,0,100,100
loop
//ハート
gsel 2 : palcolor 12 : boxf : palcolor 13
circle2 0,0,50,66 : circle2 50,0,50,66
palcolor 12 : boxf2 0,56,100,44
palcolor 13 : tri 8,56,50,99,92,56,13 : boxf2 20,30,60,30
gsel 1
repeat 13
	pos c_w*cnt+suit_x,c_h*2+suit_y
	gzoom suit_w,suit_h,2,0,0,100,100
loop
//ダイヤ
gsel 2 : palcolor 14 : boxf
squ 50,0,99,50,50,99,0,50,15
gsel 1
repeat 13
	pos c_w*cnt+suit_x,c_h*3+suit_y
	gzoom suit_w,suit_h,2,0,0,100,100
loop
tri_out

//文字部分作成
buffer2 2,bas(52),bas(8) : font font_name,font_size2 : white : boxf	//ロックスイッチボタン
black : repeat 13 : boxf2 bas(4*cnt)+bas_qua,bas_qua,bas(4)-bas_qua*2,bas(4)-bas_qua*2 : loop
magenta : repeat 13 : boxf2 bas(4*cnt)+bas_qua,bas(4)+bas_qua,bas(4)-bas_qua*2,bas(4)-bas_qua*2 : loop
gsel 1 : font font_name,font_size2
repeat 6
	cnt0=cnt
	if cnt0=4 : gsel 2
	if cnt0>=4 {
		palcolor 5-cnt0 : y=(cnt0-4)*bas(4)+rank_y-bas(4)+bas_half
	} else {
		palcolor cnt0*2+9 : y=c_h*cnt0+rank_y
	}
	repeat 13
		if cnt0>=4 : x=bas(4*cnt+2) : else : x=c_w*cnt+c_w/2
		if cnt=9 {
			pos x-(main_w(13)+main_w(9)+left_w(13))/2-left_w(9),y : mes "1"
			pos x-(main_w(13)-main_w(9))/2,y : mes "0"
		} else {
			pos x-main_w(cnt)/2-left_w(cnt),y : mes rank_n(cnt)
		}
	loop
loop
gsel 1

//エフェクト
//55:黄色 57:消える
mref vram1,66
repeat c_h
	cnt0=cnt
	y=((c_w*13+3)&0xFFFFFFFC)*cnt0+c_w*3
	repeat c_w
		poke vram1,cnt+y,((cnt+cnt0)\2)*4
	loop
loop
buffer2 4,24,24 : black : boxf : white : line 24,12,0,12 : line 12,24,12,0
line 24,24,0,0 : line 24,-1,-1,24 : black : circle2 6,6,12,12
gsel 1 : pos c_w*5,c_h*4+(c_h-c_w)/2 : gzoom c_w,c_w,4,0,0,24,24

//タグ	0:選択済 1:移動先候補
buffer2 4,bas(4),bas(2) : font font_name,font_size
magenta : boxf2 0,0,bas(2),bas(2) : black : cent "S",0,0,bas(2),bas(2)
cyan : boxf2 bas(2),0,bas(2),bas(2) : black : cent "?",bas(2),0,bas(2),bas(2)
buffer2 3,tag_w*2,tag_w
pos 0,0 : gzoom tag_w*2,tag_w,4,0,0,bas(4),bas(2)


//メイン画面
screen2 0,bas(80),bas(60),3 : celdiv 1,c_w,c_h : celdiv 3,tag_w,tag_w : celdiv 2,bas(4),bas(4)
GetSystemMenu hwnd,0 : x=stat
DeleteMenu x,0xF030,0 : DeleteMenu x,0xF120,0 : DeleteMenu x,0xF000,0	//システムメニューから不要なものを削除
SetWindowPos hwnd,0,limit((mon_w-ginfo_sizex)/2+mon_x,0),limit((mon_h-ginfo_sizey)/2+mon_y,0),0,0,0x81
//0x81=SWP_HIDEWINDOW|SWP_NOSIZE
if alpha0>=255 {
	if mesh>=16 {
		bgmode=0
	} else {
		if mesh<=0 {
			bgmode=100
		} else {
			//メッシュ背景の作成
			x=bas(32)/4*4 :	buffer2 100,x,x : black : boxf
			dim bayer,4,4
			bayer(0,0)= 0, 8, 2,10
			bayer(0,1)=12, 4,14, 6
			bayer(0,2)= 3,11, 1, 9
			bayer(0,3)=15, 7,13, 5
			mref vram100,66
			repeat x
				cnt0=cnt
				y=((x+3)&0xFFFFFFFC)*cnt0
				repeat x
					if bayer(cnt\4,cnt0\4)>=mesh : poke vram100,y+cnt,100
				loop
			loop
			dim bayer : gsel 0 : tp_fill_init 100
			bgmode=-1
		}
		GetWindowLong hwnd,-20
		SetWindowLong hwnd,-20,stat|0x80000 //WS_EX_LAYERED
		SetLayeredWindowAttributes hwnd,0x563412,0,1	//LWA_COLORKEY=1
	}
} else {
	alpha=limit(alpha0,128,255)
	if alpha<255 {
		GetWindowLong hwnd,-20
		SetWindowLong hwnd,-20,stat|0x80000 //WS_EX_LAYERED
		SetLayeredWindowAttributes hwnd,0,alpha,2	//LWA_ALPHA=2
	}
	bgmode=0
}
goto *_jump2
#deffunc bg int bgx,int bgy,int bgw,int bgh
	if bgmode<0 {
		tp_fill bgx,bgy,bgw,bgh : rd_update bgx,bgy,bgw,bgh
	} else {
		palcolor bgmode : boxf2 bgx,bgy,bgw,bgh : white : rd_update bgx,bgy,bgw,bgh
	}
	return
*_jump2

#define bg_all bg 0,0,ginfo_sx,ginfo_sy
//0:メインウィンドウ 1:カード 2:ロック用パーツ 3:タグ 4:汎用
data_reset : load
//playdata 要素1:0はプレイ回数、1はクリア回数、2はUltimate回数
//要素2:0はアコーディオン、1は王様

#define cput(%1) celput 1,%1
#define cput_t(%1) gmode 2 : celput 1,%1 : gmode 0

//タイトル
*menu
title "Accordion (Programmed by EOJ)"
font font_name,font_size : objmode 2,0
rd_start : bg_all : white : clrobj
GetTextExtentPoint32 hdc,"Accordion",9,varptr(point)
buffer2 4,point(0),point(1) : font font_name,font_size : black : boxf : green : pos 0,0 : mes "Accordion"
buffer2 200,bas(64),bas(18) : pos 0,0 : gzoom bas(64),bas(18),4,0,0,point(0),point(1)
gsel 0 : pos bas(8),bas(2) : gmode 2 : gcopy 200,0,0,bas(64),bas(18) : buffer2 200,1,1 : gsel 0
pos bas(2),bas(2) : cput 0 : pos bas(73),bas(2) : cput 13
pos bas(2),bas(12) : cput 26 : pos bas(73),bas(12) : cput 39 : gmode 0
objsize bas(24),bas(8)
pos bas(28),bas(27) : button goto "Accordion",*mode0_0
pos bas(28),bas(35) : button goto "Royal Marriage",*mode0_1
repeat 2
	cnt0=cnt
	repeat 3-cnt0
		pos bas(53),bas(28+cnt0*8+cnt*2)
		if cnt=0 : mes " ",1 : else : mes "/",1
		mes playdata(cnt,cnt0)
	loop
loop
pos bas(53),bas(44) : mes "Played\n/ Win\n/ Ultimate Win"
objsize bas(20),bas(3) : pos bas(53),bas(51) : button goto "Data Reset",*reset
cent "Programmed by EOJ(Rokugatsu no Tamago)",bas(0),bas(56),bas(80),bas(3)
gsel 0,1 : rd_end
stop

*reset
	oc_dialog "Data Reset?",,1
	if stat=IDOK {
		data_reset : save : goto *menu
	}
	stop

*mode0_0
	title "Accordion" : game=0 : goto *game_start
*mode0_1
	title "Royal Marriage" : game=1 : goto *game_start

*game_start
	//ゲーム本編
	clrobj : rd_start : bg_all
	sdim table_data,52	//場札データ
#define let_table(%1,%2) poke table_data,%1,%2
#define ctype table(%1) peek(table_data,%1)
	//カードを配置
	sdim deck,52 : sdim deck2,52
	x=0	//未配置の札の枚数
	repeat 52
		if game {
			if (cnt=37)|(cnt=38) : continue
		}
		poke deck,x,cnt : x++
	loop
	randomize
	repeat 52
		if game {
			if cnt=0 : let_table 0,37 : continue
			if cnt=51 : let_table 51,38 : continue
		}
		y=rnd(x) : let_table cnt,peek(deck,y)
		memcpy deck2,deck,x-y-1,0,y+1
		memcpy deck,deck2,x-y-1,y,0
		x--
	loop
	dim deck : dim deck2
	lock=-1	//ロックされている数字。ロックされていない場合は-1。
#define draw_table(%1) _x=bas(6*((%1)\13)+1) : _y=bas(9*((%1)/13)+6) : pos _x,_y : cput_t table(%1) : rd_update _x,_y,c_w,c_h
#define ers_table(%1) _x=bas(6*((%1)\13)+1) : _y=bas(9*((%1)/13)+6) : bg _x,_y,c_w,c_h
#define draw_lock(%1) _x=bas(2+4*(%1)) : _y=bas(50) : pos _x,_y : celput 2,(%1)+13*(lock=(%1)) : rd_update _x,_y,bas(4),bas(4)
#define draw_tag(%1,%2) _x=bas(6*((%1)\13)+1) : _y=bas(9*((%1)/13)+6) : pos _x,_y : celput 3,%2 : rd_update _x,_y,tag_w,tag_w
#define ers_tag(%1) _x=bas(6*((%1)\13)+1) : _y=bas(9*((%1)/13)+6) : bg _x,_y,tag_w,tag_w : pos _x,_y : gmode 2 : gcopy 1,(table(%1)\13)*c_w,(table(%1)/13)*c_h,tag_w,tag_w : gmode 0
#define ers_mark(%1,%2) bg %1,%2,c_w,c_h : pos %1,%2 : cput_t 57
	repeat 52 : draw_table(cnt) : loop : rd_end
	if game=0 {
		rd_start
		blue : boxf2 bas(2),bas(48),bas(52),bas(2)
		white : cent "Lock",bas(2),bas(48),bas(52),bas(2)
		rd_update bas(2),bas(48),bas(52),bas(2)
		repeat 13 : draw_lock(cnt) : loop
		rd_end
	}
	t_num=52	//場札の数
	dim candi,4	//候補
	candi_n=0	//候補数
	selected=-1	//マイナスの場合は未選択。プラスの場合は選んだアイテム。
	can_flag=0	//キャンセルフラグ
	win_flag=-1	//勝利フラグ(0:未勝利 1:勝利 2:究極勝利 -1:まだ動かしていない)
	onclick gosub *click0
	cli_flag=0	//クリックフラグ
	objsize bas(20),bas(6) : pos bas(58),bas(48) : button gosub "Restart",*resign0 : rbut_id=stat
	but_flag=0	//ボタン押しフラグ
	mx=0 : my=0
	onexit gosub *exit
	exit_flag=0	//1の時はリザルト画面へ、2の時は終了、3の時はタイトルへ
#define int_off onclick 0 : objenable rbut_id,0 : onexit gosub *dummy
#define int_off2 onclick 0 : objenable rbut_id,0
#define int_on onclick 1 : objenable rbut_id,1 : onexit gosub *exit
	repeat
		if cli_flag : gosub *click : cli_flag=0
		if but_flag : gosub *resign : but_flag=0
		if exit_flag : break
		await 1000
	loop
	onexit 0
	if exit_flag=2 : end
	if win_flag=-1 {
		if exit_flag=3 : goto *menu
		goto *game_start
	}
	//リザルト画面
	clrobj
	rd_start : bg_all
	if win_flag {
		GetTextExtentPoint32 hdc,"You Win!!!",10,varptr(point)
		buffer2 4,point(0),point(1) : font font_name,font_size : blue : boxf : yellow : pos 0,0 : mes "You Win!!!"
		gsel 0 : pos bas(8),bas(2) : gzoom bas(64),bas(18),4,0,0,point(0),point(1)
		if win_flag=2 {
			GetTextExtentPoint32 hdc,"ULTIMATE WIN!!!!!",17,varptr(point)
			buffer2 4,point(0),point(1) : font font_name,font_size : blue : boxf : yellow : pos 0,0 : mes "ULTIMATE WIN!!!!!"
			gsel 0 : pos bas(8),bas(21) : gzoom bas(64),bas(9),4,0,0,point(0),point(1)
		}
	} else {
		GetTextExtentPoint32 hdc,"You Lose...",11,varptr(point)
		buffer2 4,point(0),point(1) : font font_name,font_size : black : boxf : white : pos 0,0 : mes "You Lose..."
		gsel 0 : pos bas(8),bas(2) : gzoom bas(64),bas(18),4,0,0,point(0),point(1)
	}
	rd_end
	objsize bas(24),bas(8)
	pos bas(28),bas(37) : button goto "Next Game",*game_start
	pos bas(28),bas(45) : button goto "Go To Title",*menu
	stop

*exit
	oc_dialog "Exit?",,1
	if stat!=IDOK : return
	exit_flag=2 : resign_f=4 : int_off : clrobj
	return

#define ctype mxy_chk(%1,%2,%3,%4) ( (mx>=(%1))&(mx<(%2))&(my>=(%3))&(my<(%4)) )

*click0
	if iparam=0 : cli_flag=1 : mx=mousex : my=mousey	//左クリックのみ
	return
*click
	if selected<0 {
		//未選択状態
		if mxy_chk(bas(1),bas(78),bas(6),bas(41)) {
			x=(mx-bas(1))/bas(6) : y=(my-bas(6))/bas(9) : z=y*13+x
			if mxy_chk(bas(1+x*6),bas(6+x*6),bas(6+y*9),bas(14+y*9))&(z<t_num) {
				//移動先候補検索
				candi_n=0
				if game=0 {
					//アコーディオン
					//1マス左
					if z>=1 {
						if (rank(table(z))=rank(table(z-1)))|(suit(table(z))=suit(table(z-1))) {
							if rank(table(z-1))!=lock : candi(candi_n)=z-1 : candi_n++
						}
					}
					//3マス左
					if z>=3 {
						if (rank(table(z))=rank(table(z-3)))|(suit(table(z))=suit(table(z-3))) {
							if rank(table(z-3))!=lock : candi(candi_n)=z-3 : candi_n++
						}
					}
				} else {
					//王様
					//2マス左
					if z>=2 {
						if (rank(table(z))=rank(table(z-2)))|(suit(table(z))=suit(table(z-2))) {
							candi(candi_n)=z-2 : candi_n++
						}
					}
					//3マス左
					if z>=3 {
						if (rank(table(z))=rank(table(z-3)))|(suit(table(z))=suit(table(z-3))) {
							candi(candi_n)=z-3 : candi_n++
						}
					}
					//2マス右
					if z<=t_num-3 {
						if (rank(table(z))=rank(table(z+2)))|(suit(table(z))=suit(table(z+2))) {
							candi(candi_n)=z+2 : candi_n++
						}
					}
					//3マス右
					if z<=t_num-4 {
						if (rank(table(z))=rank(table(z+3)))|(suit(table(z))=suit(table(z+3))) {
							candi(candi_n)=z+3 : candi_n++
						}
					}
				}
				if candi_n {
					selected=z
					rd_start : draw_tag selected,0
					repeat candi_n
						draw_tag candi(cnt),1
					loop
					rd_end
				}
			}
			return
		}
	} else {
		//選択済み状態
		can_flag=1
		if mxy_chk(bas(1),bas(78),bas(6),bas(41)) {
			x=(mx-bas(1))/bas(6) : y=(my-bas(6))/bas(9) : z=y*13+x
			if mxy_chk(bas(1+x*6),bas(6+x*6),bas(6+y*9),bas(14+y*9)) {
				repeat candi_n
					if candi(cnt)=z : can_flag=0 : break	//can_flagが0の時点でzには何かしらが入っている
				loop
			}
		}
		rd_start
		if can_flag|game : ers_tag selected
		repeat candi_n
			if can_flag|game|(candi(cnt)!=z) : ers_tag candi(cnt)
		loop
		if can_flag=0 {
			//移動アニメーション
			int_off : await 1
			if game=0 {
				//アコーディオン
				let_table z,table(selected) : draw_table(z)
				pos _x,_y : cput_t 55	//_xと_yにはカードの座標が入っている
				x=bas((selected\13)*6+1) : y=bas((selected/13)*9+6)
				ers_mark x,y
				rd_end : await 400 : rd_start
				ers_table z : draw_table z : ers_table selected 
				x=selected : y=selected+1
				repeat
					if y>=t_num : break
					let_table x,table(y) : draw_table x : ers_table y
					rd_end : await 33 : rd_start
					x++ : y++
				loop
				t_num--
				if (win_flag=-1)&(t_num<52) {
					win_flag=0
					objprm rbut_id,"Resign"
					playdata(0,game)++ : save
				}
				if (win_flag<=0)&(t_num<=5) {
					win_flag=1
					objprm rbut_id,"Finish"
					playdata(1,game)++ : save
				}
				if t_num<=1 {
					win_flag=2
					playdata(2,game)++ : save
					await 1000
					exit_flag=1
				}
			} else {
				//王様
				if z>selected : x=z : z=selected : selected=x
				a=selected-z-1	//消去する数
				repeat a,z+1
					x=bas((cnt\13)*6+1) : y=bas((cnt/13)*9+6)
					ers_mark x,y
					rd_end : await 400 : rd_start
					ers_table(cnt)
				loop
				x=z+1 : y=selected
				repeat
					if y>=t_num : break
					let_table x,table(y) : draw_table(x) : ers_table(y)
					rd_end : await 33 : rd_start
					x++ : y++
				loop
				t_num-=a
				if (win_flag=-1)&(t_num<52) {
					win_flag=0
					objprm rbut_id,"Resign"
					playdata(0,game)++
					save
				}
				if t_num<=2 {
					win_flag=1
					playdata(1,game)++ : playdata(2,game)++
					save
					await 1000
					exit_flag=1
				}
			}
			if exit_flag=0 : int_on
		}
		selected=-1 : candi_n=0
		rd_end
		if can_flag=0 : return
		can_flag=0
	}
	//ロック
	if game=0 {
		if mxy_chk(bas(2),bas(54),bas(50),bas(54)) {
			rd_start
			x=(mx-bas(2))/bas(4)
			if lock=x : lock=-1 : else : y=lock : lock=x : draw_lock(y)
			draw_lock(x) : rd_end
		}
	}
	return

*resign0
	but_flag=1 : return
*resign
	if win_flag=-1 {
		int_off2	//割り込みを無効にする
		buffer2 200,bas(22),bas(14)	: pos 0,0 : gcopy 0,bas(29),bas(22),bas(22),bas(14)
		gsel 0 : rd_start : palcolor 101 : boxf2 bas(29),bas(22),bas(22),bas(3)
		palcolor 102 : cent "Restart?",bas(29),bas(22),bas(22),bas(3)
		palcolor 103 : boxf2 bas(29),bas(25),bas(22),bas(11) : white
		rd_update bas(29),bas(22),bas(22),bas(14) : rd_end
		objsize bas(3),bas(3) : pos bas(48),bas(22) : button gosub "X",*resign3 : rlis_id0=stat
		objsize bas(20),bas(3)
		pos bas(30),bas(26) : button gosub "OK(Restart)",*resign1 : rlis_id1=stat
		pos bas(30),bas(29) : button gosub "Go to title",*resign2 : rlis_id2=stat
		pos bas(30),bas(32) : button gosub "Cancel",*resign3 : rlis_id3=stat
		GetWindowLong objinfo(rlis_id3,2),-16 : SetWindowLong objinfo(rlis_id3,2),-16,stat|1
		resign_f=0
		repeat
			if resign_f : break
			await 1000
		loop
		if resign_f=4 : return
		rd_start : pos bas(29),bas(22) : gcopy 200,0,0,bas(22),bas(14)
		rd_update bas(29),bas(22),bas(22),bas(14) : rd_end : buffer2 200,1,1 : gsel 0
		clrobj rlis_id0,rlis_id0 : clrobj rlis_id1,rlis_id1 : clrobj rlis_id2,rlis_id2 : clrobj rlis_id3,rlis_id3
		if resign_f=1 : exit_flag=1 : return
		if resign_f=2 : exit_flag=3 : return
		int_on	//割り込みを有効にする
		return
	}
	if win_flag : oc_dialog "Finish?" : else : oc_dialog "Resign?",,1
	if stat!=IDOK : return
	int_off : exit_flag=1
	return
*resign1
	resign_f=1 : return
*resign2
	resign_f=2 : return
*resign3
	resign_f=3 : return

*dummy
	return





//戻る