summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscw <scw@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2004-07-25 15:24:04 +0800
committerscw <scw@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2004-07-25 15:24:04 +0800
commitd05ba58a0f1abb4e25795d6d083e1390ed166fc2 (patch)
treecc0d9e2a474adcdd4c97873a611262eec8d810cb
parentda8da8ab0be8b2100667405297e717c84670b4d8 (diff)
downloadpttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar.gz
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar.bz2
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar.lz
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar.xz
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.tar.zst
pttbbs-d05ba58a0f1abb4e25795d6d083e1390ed166fc2.zip
Go game add color board (dirty hack @@),
and allow throwing waterball in games. git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@2144 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--mbbsd/go.c318
-rw-r--r--mbbsd/io.c16
-rw-r--r--mbbsd/talk.c2
3 files changed, 202 insertions, 134 deletions
diff --git a/mbbsd/go.c b/mbbsd/go.c
index 18f04120..0ad0d0ae 100644
--- a/mbbsd/go.c
+++ b/mbbsd/go.c
@@ -13,11 +13,14 @@
#define BBLACK (1) /* 黑子 */
#define BWHITE (2) /* 白子 */
-#define redoln() (void)0
+#define redoln() redoscr()
#define BRDSIZ (19) /* 棋盤單邊大小 */
-#define BGOTO(x, y) move(20 - y , x * 2 + 4)
+#define move(y,x) move(y, (x) + ((y) < 2 || (y) > 20 ? 0 : \
+ (x) > 43 ? 11 : 8))
+#define iBGOTO(x,y) move(20 - (y) , (x) * 2 + 4 - 8),do_move(20-(y),(x)*2+4) // really dirty ><
+#define BGOTO(x,y) move(20 - (y) , (x) * 2 + 4),do_move(20-(y),(x)*2+4)
static unsigned char go[BRDSIZ][BRDSIZ];
static unsigned char l[BRDSIZ][BRDSIZ];
@@ -445,7 +448,7 @@ go_key(int fd, int ch, Horder_t *mv)
if (fd) add_io(fd, 0);
move(21, 9);
clrtoeol();
- outs(" ");
+ //outs(" ");
vx = ch - 'a';
if (ch > 'i')
@@ -613,17 +616,29 @@ GO_result(void)
void
GO_cleantable()
{
- int i, j;
-
- move(1, 5);
- for (i = 0; i < BRDSIZ; ++i)
- prints("%c ", locE[i]);
- for (i = 0; i < BRDSIZ; ++i) {
- move(2 + i, 0);
- prints("%3d", BRDSIZ - i);
- for (j = 0; j < BRDSIZ; ++j)
- GO_blank(i, j);
- }
+ move(1, 0);
+ outs(
+ " A B C D E F G H J K L M N O P Q R S T\n"
+ " 19 ┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐ \n"
+ " 18 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 17 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 16 ├┼┼+┼┼┼┼┼+┼┼┼┼┼+┼┼┤ \n"
+ " 15 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 14 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 13 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 12 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 11 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 10 ├┼┼+┼┼┼┼┼+┼┼┼┼┼+┼┼┤ \n"
+ " 9 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 8 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 7 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 6 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 5 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 4 ├┼┼+┼┼┼┼┼+┼┼┼┼┼+┼┼┤ \n"
+ " 3 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 2 ├┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┤ \n"
+ " 1 └┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘ \n"
+ );
}
int
@@ -634,6 +649,7 @@ gochess(int fd)
time_t mtime, htime, btime;
int i, j, ch = 0, passflag, endflag, totalgo, timeflag, is_view;
unsigned char mhand, hhand;
+ int scr_need_redraw = 1;
GO_init();
@@ -683,12 +699,80 @@ gochess(int fd)
for(;;)
{
+ if(scr_need_redraw){
+ move(2, 46);
+ prints("%s 方提子數:%3d", bw_chess[me - 1], hk);
+ move(3, 46);
+ prints("%s 方提子數:%3d", bw_chess[he - 1], mk);
+
+ move(8, 46);
+ clrtoeol();
+ if (endflag)
+ outs("請清除死子,以便計算勝負");
+ else if (my->turn)
+ prints("輪到自己下了.... 我是 %s", bw_chess[me - 1]);
+ else
+ outs("等待對方下子....");
+
+
+ move(10, 46);
+ clrtoeol();
+ if (totalgo > 0)
+ {
+ if (pool[totalgo - 1].x == -1 || pool[totalgo - 1].y == -1)
+ prints("%s #%-3d PASS 上一手 ", win ? bw_chess[(totalgo - 1) & 1] : bw_chess[totalgo & 1], totalgo);
+ else
+ prints("%s #%-3d %.1s%-2d 上一手 ", win ? bw_chess[(totalgo - 1) & 1] : bw_chess[totalgo & 1], totalgo, locE + pool[totalgo - 1].x, pool[totalgo - 1].y + 1);
+ }
+
+ for (i = totalgo - 1;i > 0 && totalgo - i <= 10;i--)
+ {
+ move(10 + totalgo - i, 46);
+ clrtoeol();
+ if (pool[i - 1].x == -1 || pool[i - 1].y == -1)
+ prints("%s #%-3d PASS", win ? bw_chess[(i - 1) & 1] : bw_chess[i & 1], i);
+ else
+ prints("%s #%-3d %.1s%-2d ", win ? bw_chess[(i - 1) & 1] : bw_chess[i & 1], i, locE + pool[i - 1].x, pool[i - 1].y + 1);
+ }
+
+ move(21, 46);
+
+ if (v == pool)
+ {
+ if (me == BWHITE && win != 0)
+ outs("\033[1;33m按 x 讓子 y 不限時 Ctrl-C 中止棋局\033[m");
+ else
+ outs("\033[1;33m按 Ctrl-C 中止棋局\033[m");
+ }
+ else if (passflag && my->turn)
+ {
+ if (endflag)
+ outs("\033[1;33m對方 DONE,己方 DONE 就計算結果\033[m");
+ else
+ outs("\033[1;33m對方 PASS,己方 PASS 就結束棋局\033[m");
+ }
+ else if (v > pool)
+ clrtoeol();
+
+ if (endflag)
+ outmsg("\033[1;33;42m 下棋 \033[;31;47m (←↑↓→)\033[30m移動 \033[31m(空白鍵/ENTER)\033[30m下子 \033[31m(v)\033[30m傳訊 \033[31m(z)\033[30m投降 \033[31m(w)\033[30mDONE \033[31m(u)\033[30m回復 \033[m");
+ else
+ outmsg("\033[1;33;42m 下棋 \033[;31;47m (←↑↓→)\033[30m移動 \033[31m(空白鍵/ENTER)\033[30m下子 \033[31m(v)\033[30m傳訊 \033[31m(z)\033[30m投降 \033[31m(w)\033[30mPASS \033[m");
+
+ redoscr();
+ scr_need_redraw = 0;
+ }
+
if (endflag || timeflag)
{
- move(5, 46);
- prints("%s 方時間:----- --", bw_chess[me - 1]);
- move(6, 46);
- prints("%s 方時間:----- --", bw_chess[he - 1]);
+ char buf[128];
+ int n;
+ //move(5, 46);
+ n = sprintf(buf, "\033[6;47H%s 方時間:----- --", bw_chess[me - 1]);
+ output(buf, n);
+ //move(6, 46);
+ n = sprintf(buf, "\033[7;47H%s 方時間:----- --", bw_chess[he - 1]);
+ output(buf, n);
}
else
{
@@ -728,75 +812,30 @@ gochess(int fd)
}
}
move(5, 46);
- prints("%s 方時間:%02ld:%02ld ", bw_chess[me - 1], mtime / 60, mtime % 60);
- if (mhand <= 25)
- prints("%2d 手", 25 - mhand);
- move(6, 46);
- prints("%s 方時間:%02ld:%02ld ", bw_chess[he - 1], htime / 60, htime % 60);
- if (hhand <= 25)
- prints("%2d 手", 25 - hhand);
- }
- btime = now;
- move(2, 46);
- prints("%s 方提子數:%3d", bw_chess[me - 1], hk);
- move(3, 46);
- prints("%s 方提子數:%3d", bw_chess[he - 1], mk);
-
- move(8, 46);
- clrtoeol();
- if (endflag)
- outs("請清除死子,以便計算勝負");
- else if (my->turn)
- prints("輪到自己下了.... 我是 %s", bw_chess[me - 1]);
- else
- outs("等待對方下子....");
-
-
- move(10, 46);
- clrtoeol();
- if (totalgo > 0)
- {
- if (pool[totalgo - 1].x == -1 || pool[totalgo - 1].y == -1)
- prints("%s #%-3d PASS 上一手 ", win ? bw_chess[(totalgo - 1) % 2] : bw_chess[totalgo % 2], totalgo);
- else
- prints("%s #%-3d %.1s%-2d 上一手 ", win ? bw_chess[(totalgo - 1) % 2] : bw_chess[totalgo % 2], totalgo, locE + pool[totalgo - 1].x, pool[totalgo - 1].y + 1);
- }
-
- for (i = totalgo - 1;i > 0 && totalgo - i <= 10;i--)
- {
- move(10 + totalgo - i, 46);
clrtoeol();
- if (pool[i - 1].x == -1 || pool[i - 1].y == -1)
- prints("%s #%-3d PASS", win ? bw_chess[(i - 1) & 1] : bw_chess[i & 1], i);
- else
- prints("%s #%-3d %.1s%-2d ", win ? bw_chess[(i - 1) & 1] : bw_chess[i & 1], i, locE + pool[i - 1].x, pool[i - 1].y + 1);
- }
-
- move(21, 46);
-
- if (v == pool)
- {
- if (me == BWHITE && win != 0)
- outs("\033[1;33m按 x 讓子 y 不限時 Ctrl-C 中止棋局\033[m");
- else
- outs("\033[1;33m按 Ctrl-C 中止棋局\033[m");
- }
- else if (passflag && my->turn)
- {
- if (endflag)
- outs("\033[1;33m對方 DONE,己方 DONE 就計算結果\033[m");
- else
- outs("\033[1;33m對方 PASS,己方 PASS 就結束棋局\033[m");
+ /* move() only move pointer in screen.c, doesn't move
+ * curses correctly */
+ //do_move(5, 35);
+ {
+ char buf[128];
+ int n;
+ //move(5, 46);
+ n = sprintf(buf, "\033[6;47H%s 方時間:%02ld:%02ld ",
+ bw_chess[me - 1], mtime / 60, mtime % 60);
+ if (mhand <= 25)
+ n += sprintf(buf + n, "%2d 手", 25 - mhand);
+ output(buf, n);
+ //move(6, 46);
+ n = sprintf(buf, "\033[7;47H%s 方時間:%02ld:%02ld ",
+ bw_chess[he - 1], htime / 60, htime % 60);
+ if (hhand <= 25)
+ n += sprintf(buf + n, "%2d 手", 25 - hhand);
+ output(buf, n);
+ }
}
- else if (v > pool)
- clrtoeol();
-
- if (endflag)
- outmsg("\033[1;33;42m 下棋 \033[;31;47m (←↑↓→)\033[30m移動 \033[31m(空白鍵/ENTER)\033[30m下子 " /*\033[31m(v)\033[30m傳訊 */ "\033[31m(z)\033[30m投降 \033[31m(w)\033[30mDONE \033[31m(u)\033[30m回復 \033[m");
- else
- outmsg("\033[1;33;42m 下棋 \033[;31;47m (←↑↓→)\033[30m移動 \033[31m(空白鍵/ENTER)\033[30m下子 " /*\033[31m(v)\033[30m傳訊 */ "\033[31m(z)\033[30m投降 \033[31m(w)\033[30mPASS \033[m");
+ btime = now;
- BGOTO(mv.x, mv.y);
+ iBGOTO(mv.x, mv.y);
/*
if (ch == -1 && is_view)
@@ -805,36 +844,37 @@ gochess(int fd)
ch = igetch();
- /* 對戰中丟水球, 暫不支援
if (ch == 'v')
{
//extern screenline *big_picture;
- screenline* screen0 = calloc(t_lines, sizeof(screenline));
+ screenline_t* screen0 = calloc(t_lines, sizeof(screenline_t));
int y, x;
- memcpy(screen0, big_picture, t_lines * sizeof(screenline));
+ memcpy(screen0, big_picture, t_lines * sizeof(screenline_t));
add_io(0, 0);
getyx(&y, &x);
if (ch == 'v')
{
- extern char watermode;
+ //extern char watermode;
- watermode = 2;
- my_write(my->destuip->pid, "丟水球過去:");
- watermode = 0;
+ //watermode = 2;
+ my_write(0, "丟水球過去:", my->mateid, WATERBALL_GENERAL, &SHM->uinfo[my->destuip]);
+ //watermode = 0;
}
+ /* ??? scw: when will these code be executed?
else
{
show_last_call_in();
my_write(currutmp->msgs[0].last_pid, "水球丟回去:");
}
+ */
move(y, x);
- memcpy(big_picture, screen0, t_lines * sizeof(screenline));
+ memcpy(big_picture, screen0, t_lines * sizeof(screenline_t));
free(screen0);
- redoscr();
add_io(fd, 0);
+ scr_need_redraw = 1;
continue;
- } else */ if (ch == 'x') {
+ } else if (ch == 'x') {
if (v == pool && me == BWHITE && win != 0)
{
char buf[4];
@@ -962,11 +1002,11 @@ gochess(int fd)
if (go[i][j])
{
outs(bw_chess[go[i][j] - 1]);
- redoln();
}
else
GO_blank(i, j);
}
+ redoscr();
mv.x = mv.y = -7;
if (send(fd, &mv, sizeof(Horder_t), 0) != sizeof(Horder_t))
break;
@@ -989,6 +1029,7 @@ gochess(int fd)
if (ch == I_OTHERDATA)
{
ch = recv(fd, &mv, sizeof(Horder_t), 0);
+ scr_need_redraw = 1;
if (ch <= 0)
{
@@ -1017,8 +1058,11 @@ gochess(int fd)
continue;
}
- if (mv.x == -5 && mv.y == -5)
+ if (mv.x == -5 && mv.y == -5){
+ move(8, 46);
+ outs("對方斷線.... ");
break;
+ }
if (mv.x == -4 && mv.y == -4)
{
@@ -1123,7 +1167,7 @@ gochess(int fd)
*/
mv.x = (x - 4) / 2;
mv.y = 20 - y;
- BGOTO(mv.x, mv.y);
+ iBGOTO(mv.x, mv.y);
if (me == BWHITE)
ch = -1;
@@ -1143,12 +1187,11 @@ gochess(int fd)
go[(int)mv.x][(int)mv.y] = he;
BGOTO(mv.x, mv.y);
outs(bw_chess[he - 1]);
- redoln();
GO_examboard(me);
my->turn = 1;
- htime -= time(0) - btime;
- btime = time(0);
+ htime -= now - btime;
+ btime = now;
passflag = 0;
if (me == BWHITE)
@@ -1178,8 +1221,8 @@ gochess(int fd)
GO_add(&mv);
totalgo++;
- mtime -= time(0) - btime;
- btime = time(0);
+ mtime -= now - btime;
+ btime = now;
if (--mhand <= 0)
{
mtime = 12 * 60;
@@ -1187,7 +1230,6 @@ gochess(int fd)
}
BGOTO(mv.x, mv.y);
outs(bw_chess[me - 1]);
- redoln();
go[(int)mv.x][(int)mv.y] = me;
GO_examboard(he);
if (send(fd, &mv, sizeof(Horder_t), 0) != sizeof(Horder_t))
@@ -1196,12 +1238,14 @@ gochess(int fd)
if (me == BWHITE)
ch = -1;
+ scr_need_redraw = 1;
}
}
}
add_io(0, 0);
close(fd);
+ redoscr();
igetch();
@@ -1248,6 +1292,7 @@ GoBot(void)
unsigned char tmp_l[2][BRDSIZ][BRDSIZ];
unsigned char tmp_ml[2][BRDSIZ][BRDSIZ];
int tmp_lib[2], tmp_mik[2], tmp_mjk[2], tmp_hik[2], tmp_hjk[2];
+ int scr_need_redraw = 1;
GO_init();
@@ -1281,33 +1326,37 @@ GoBot(void)
for(;;)
{
- move(8, 46);
- clrtoeol();
- prints("輪到 %s 方下了....", bw_chess[me - 1]);
-
- move(10, 46);
- clrtoeol();
- if (totalgo > 0)
- {
- if (pool[totalgo - 1].x == -1 || pool[totalgo - 1].y == -1)
- prints("%s #%-3d PASS 上一手 ", bw_chess[(totalgo - 1) & 1], totalgo);
- else
- prints("%s #%-3d %.1s%-2d 上一手 ", bw_chess[(totalgo - 1) & 1], totalgo, locE + pool[totalgo - 1].x, pool[totalgo - 1].y + 1);
- }
+ if(scr_need_redraw){
+ move(8, 46);
+ clrtoeol();
+ prints("輪到 %s 方下了....", bw_chess[me - 1]);
- for (i = totalgo - 1;i > 0 && totalgo - i <= 10;i--)
- {
- move(10 + totalgo - i, 46);
+ move(10, 46);
clrtoeol();
- if (pool[i - 1].x == -1 || pool[i - 1].y == -1)
- prints("%s #%-3d PASS", bw_chess[(i - 1) % 2], i);
- else
- prints("%s #%-3d %.1s%-2d ", bw_chess[(i - 1) % 2], i, locE + pool[i - 1].x, pool[i - 1].y + 1);
- }
+ if (totalgo > 0)
+ {
+ if (pool[totalgo - 1].x == -1 || pool[totalgo - 1].y == -1)
+ prints("%s #%-3d PASS 上一手 ", bw_chess[(totalgo - 1) & 1], totalgo);
+ else
+ prints("%s #%-3d %.1s%-2d 上一手 ", bw_chess[(totalgo - 1) & 1], totalgo, locE + pool[totalgo - 1].x, pool[totalgo - 1].y + 1);
+ }
- outmsg(" 打譜  (←↑↓→)移動 (空白鍵/ENTER)下子 (u)回上一步 \033[31m(z)\033[30m離開 ");
+ for (i = totalgo - 1;i > 0 && totalgo - i <= 10;i--)
+ {
+ move(10 + totalgo - i, 46);
+ clrtoeol();
+ if (pool[i - 1].x == -1 || pool[i - 1].y == -1)
+ prints("%s #%-3d PASS", bw_chess[(i - 1) & 1], i);
+ else
+ prints("%s #%-3d %.1s%-2d ", bw_chess[(i - 1) & 1], i, locE + pool[i - 1].x, pool[i - 1].y + 1);
+ }
+
+ outmsg(" 打譜  (←↑↓→)移動 (空白鍵/ENTER)下子 (u)回上一步 \033[31m(z)\033[30m離開 ");
+ redoscr();
+ scr_need_redraw = 0;
+ }
- BGOTO(mv.x, mv.y);
+ iBGOTO(mv.x, mv.y);
ch = igetch();
@@ -1315,6 +1364,9 @@ GoBot(void)
break;
else if (ch == 'u')
{
+ int j;
+ if (!totalgo)
+ continue;
memset(go, 0, sizeof(go));
memset( l, 0, sizeof(go));
memset(ml, 0, sizeof(go));
@@ -1333,12 +1385,8 @@ GoBot(void)
/* film_out(FILM_GO, 1); */
totalgo--;
- GO_cleantable();
for (i = 0;i < totalgo;i++)
{
- BGOTO(pool[i].x, pool[i].y);
- outs(bw_chess[me - 1]);
- redoln();
go[(int)pool[i].x][(int)pool[i].y] = me;
GO_examboard(he);
memcpy(&tmp_go[me - 1], &go, sizeof(l));
@@ -1362,6 +1410,14 @@ GoBot(void)
go[(int)pool[i].x][(int)pool[i].y] = he;
GO_examboard(me);
}
+ GO_cleantable();
+ for (i = 0; i < BRDSIZ; ++i)
+ for(j = 0; j < BRDSIZ; ++j)
+ if (go[i][j]) {
+ BGOTO(i, j);
+ outs(bw_chess[go[i][j] - 1]);
+ }
+ scr_need_redraw = 1;
mv = *(--v);
}
else
@@ -1372,7 +1428,6 @@ GoBot(void)
totalgo++;
BGOTO(mv.x, mv.y);
outs(bw_chess[me - 1]);
- redoln();
go[(int)mv.x][(int)mv.y] = me;
GO_examboard(he);
memcpy(&tmp_go[me - 1], &go, sizeof(l));
@@ -1395,6 +1450,7 @@ GoBot(void)
hjk = tmp_hjk[me - 1];
go[(int)mv.x][(int)mv.y] = he;
GO_examboard(me);
+ scr_need_redraw = 1;
}
}
}
diff --git a/mbbsd/io.c b/mbbsd/io.c
index 584faa29..129aba90 100644
--- a/mbbsd/io.c
+++ b/mbbsd/io.c
@@ -151,11 +151,23 @@ dogetch()
/* raise(SIGHUP); */
}
- if (len == 0)
+ if (len == 0){
+#ifdef OUTTA_TIMER
+ now = SHM->GV2.e.now;
+#else
+ now = time(0);
+#endif
return I_TIMEOUT;
+ }
- if (i_newfd && FD_ISSET(i_newfd, &readfds))
+ if (i_newfd && FD_ISSET(i_newfd, &readfds)){
+#ifdef OUTTA_TIMER
+ now = SHM->GV2.e.now;
+#else
+ now = time(0);
+#endif
return I_OTHERDATA;
+ }
}
#ifdef NOKILLWATERBALL
if( currutmp && currutmp->msgcount && !reentrant_write_request )
diff --git a/mbbsd/talk.c b/mbbsd/talk.c
index 78c3c251..0be62198 100644
--- a/mbbsd/talk.c
+++ b/mbbsd/talk.c
@@ -603,7 +603,7 @@ my_write2(void)
* 3. 上站aloha flag = WATERBALL_ALOHA, 2 (pre-edit)
* 4. 廣播 flag = WATERBALL_SYSOP, 3 if SYSOP
* flag = WATERBALL_PREEDIT, 1 otherwise
- * 5. 丟水球 flag = WATERBALL_GENGRAL, 0
+ * 5. 丟水球 flag = WATERBALL_GENERAL, 0
* 6. my_write2 flag = WATERBALL_CONFIRM, 4 (pre-edit but confirm)
* 7. (when defined PLAY_ANGEL)
* 呼叫小天使 flag = WATERBALL_ANGEL, 5 (id = "小天使")