UWSCでヌメロン風?ゲーム

UWSC公式掲示板に、懐かしいゲームがあったので、対戦式にしてみた。
Master Mindとか、Hit & Errorとか呼ばれるゲームですよね。



スクリプト

Linersさんのを流用して、対戦にした。
自分とやっても面白くないので、Randomを作った、、、けど、つまらないので、
少しだけ工夫を入れたAlgを作成。
ちゃんとしたAIは面倒なので、ま、ほとんどRandomですけどね。

OPTION EXPLICIT

ACW(GETID(GET_LOGPRINT_WIN),,, 240, 600)
PRINT
PRINT "======  Numer0n Base  ======"
PRINT "Call EAT BITE  Call EAT BITE"

DIM a[1][2], p[1][2], s[1], e[1], b[1], na[1], n
HASHTBL x0, x1, r0, r1

FOR n = 0 TO 1
	na[n] = "Get" + SLCTBOX(SLCT_STR, 0, "Player " + n, "Input", "Alg", "Random")
	IF LENGTH(na[n]) < 6 THEN EXITEXIT
NEXT
x0[0] = "==  Number 0  =="
Get(na[0], a[0], x0, r0, r1)
x0[0] = "==  Number 1  =="
Get(na[1], a[1], x0, r0, r1)

n = 0
REPEAT
	x0 = HASH_REMOVEALL
	x0[0] = "==  Call 0  =="
	s[0] = Get(na[0], p[0], x0, r0, r1)
	IF s[0] = "000" THEN EXITEXIT
	x1 = HASH_REMOVEALL
	x1[0] = "==  Call 1  =="
	s[1] = Get(na[1], p[1], x1, r1, r0)
	IF s[1] = "000" THEN EXITEXIT
	e[0] = Check(a[1], p[0], b[0])
	e[1] = Check(a[0], p[1], b[1])
	PRINT s[0] + "   " + e[0] + "   " + b[0] + "   " + s[1] + "   " + e[1] + "   " + b[1]
	r0[n] = s[0] + e[0] + b[0]
	r1[n] = s[1] + e[1] + b[1]
	n = n + 1
UNTIL e[0] = 3 OR e[1] = 3
b[0] = -1
IF e[0] = 3 THEN b[0] = 0
IFB e[1] = 3 THEN
	IF b[0] = 0 THEN b[0] = "0/1" ELSE b[0] = 1
ENDIF
b[1] = JOIN(a, "")
PRINT "A: " + COPY(b[1], 1, 3) + " " + COPY(b[1], 4, 3)
IFB b[0] >= 0 THEN
	IF MSGBOX("Player" + b[0] + " win! " + n + "<#CR><#CR> Retry?", BTN_YES OR BTN_NO) = BTN_YES THEN POFF(P_UWSC_REEXEC, TRUE)
ENDIF


FUNCTION Check(a[], p[], var b)
	RESULT = (a[0] = p[0]) + (a[1] = p[1]) + (a[2] = p[2])
	b = (a[0] = p[1] OR a[0] = p[2]) + (a[1] = p[0] OR a[1] = p[2]) + (a[2] = p[0] OR a[2] = p[1])
FEND

FUNCTION Get(funcName, var a[], var b[], var c[], var d[])
	WHILE EVAL(funcName + "(a,b,c,d)") AND (a[0] = a[1] OR a[0] = a[2] OR a[1] = a[2]); WEND
	RESULT = JOIN(a, "")
FEND

FUNCTION GetRandom(var a[], var b[], var c[], var d[])
	DIM loop = TRUE, i
	WHILE loop
		a[0] = RANDOM(10)
		a[1] = RANDOM(10)
		a[2] = RANDOM(10)
		loop = FALSE
		FOR i = 0 TO LENGTH(b) - 1
			loop = loop OR (a[0] = b[i, HASH_KEY] OR a[1] = b[i, HASH_KEY] OR a[2] = b[i, HASH_KEY])
		NEXT
	WEND
	RESULT = TRUE
FEND

FUNCTION GetInput(var a[], var b[], var c[], var d[])
	DIM s = INPUT(b[0])
	IF s = "" THEN s = "000"
	IF LENGTH(s) <> 3 OR CHKNUM(s) = 0 THEN s = 0 ELSE s = VAL(s)
	a[0] = INT(s / 100)
	a[1] = INT((s mod 100) / 10)
	a[2] = s mod 10
	RESULT = (s <> 0)
FEND

FUNCTION GetAlg(var a[], var b[], var c[], var d[])
	DIM m = LENGTH(c), i, j, k, l
	RESULT = FALSE
	b = HASH_REMOVEALL
	FOR j = 0 TO m - 1
		FOR i = 1 TO 3
			b[VAL(COPY(c[j], i, 1))] = 1
		NEXT
	NEXT
	HASHTBL k1, k2, k3
	FOR i = 0 TO 9
		IFB m < 3 OR b[i, HASH_EXISTS] THEN
			k1[i] = 1
			k2[i] = 1
			k3[i] = 1
		ELSEIF VAL(COPY(c[0],4,1))+VAL(COPY(c[0],5,1))+VAL(COPY(c[1],4,1))+VAL(COPY(c[1],5,1))+VAL(COPY(c[2],4,1))+VAL(COPY(c[2],5,1)) < 3 THEN
			k1[i] = 1
			k2[i] = 1
			k3[i] = 1
		ENDIF
	NEXT
	FOR i = 0 TO m - 1
		SELECT COPY(c[i], 4, 2)
		CASE "00"
			FOR j = 1 TO 3
				l = VAL(COPY(c[i], j, 1))
				k = k1[l, HASH_REMOVE]
				k = k2[l, HASH_REMOVE]
				k = k3[l, HASH_REMOVE]
				b[l] = 1
			NEXT
		CASE "01", "02"
			FOR j = 1 TO 3
				l = VAL(COPY(c[i], j, 1))
				IF j = 1 THEN k = k1[l, HASH_REMOVE]
				IF j = 2 THEN k = k2[l, HASH_REMOVE]
				IF j = 3 THEN k = k3[l, HASH_REMOVE]
			NEXT
		CASE "10", "20"
			FOR j = 1 TO 3
				l = VAL(COPY(c[i], j, 1))
				IF j <> 1 THEN k = k1[l, HASH_REMOVE]
				IF j <> 2 THEN k = k2[l, HASH_REMOVE]
				IF j <> 3 THEN k = k3[l, HASH_REMOVE]
			NEXT
		CASE "11"
			// nop
		CASE "12"
			l = VAL(COPY(c[i], 1, 1))
			IFB k1[l, HASH_EXISTS] THEN
				a[0] = l
				a[1] = VAL(COPY(c[i], 3, 1))
				a[2] = VAL(COPY(c[i], 2, 1))
			ELSE
				l = VAL(COPY(c[i], 2, 1))
				IFB k2[l, HASH_EXISTS] THEN
					a[0] = VAL(COPY(c[i], 3, 1))
					a[1] = l
					a[2] = VAL(COPY(c[i], 1, 1))
				ELSE
					a[0] = l
					a[1] = VAL(COPY(c[i], 1, 1))
					a[2] = VAL(COPY(c[i], 3, 1))
				ENDIF
			ENDIF
			RESULT = TRUE
		CASE "03"
			l = VAL(COPY(c[i], 2, 1))
			IFB k1[l, HASH_EXISTS] THEN
				IFB k1[VAL(COPY(c[i], 3, 1)), HASH_EXISTS] AND k2[VAL(COPY(c[i], 1, 1)), HASH_EXISTS] THEN
					IFB k2[VAL(COPY(c[i], 3, 1)), HASH_EXISTS] AND k3[VAL(COPY(c[i], 1, 1)), HASH_EXISTS] THEN
						a[0] = l
						a[1] = VAL(COPY(c[i], 3, 1))
						a[2] = VAL(COPY(c[i], 1, 1))
					ELSE
						a[0] = VAL(COPY(c[i], 3, 1))
						a[1] = VAL(COPY(c[i], 1, 1))
						a[2] = l
					ENDIF
				ELSE
					a[0] = l
					a[1] = VAL(COPY(c[i], 3, 1))
					a[2] = VAL(COPY(c[i], 1, 1))
				ENDIF
			ELSE
				a[0] = VAL(COPY(c[i], 3, 1))
				a[1] = VAL(COPY(c[i], 1, 1))
				a[2] = l
			ENDIF
			RESULT = TRUE
		SELEND
	NEXT
	IFB RESULT THEN
		// nop
	ELSEIF m > 2 THEN
		j = 0
		REPEAT
			a[0] = k1[RANDOM(LENGTH(k1)), HASH_KEY]
			a[1] = k2[RANDOM(LENGTH(k2)), HASH_KEY]
			a[2] = k3[RANDOM(LENGTH(k3)), HASH_KEY]
			IFB a[0] <> a[1] AND a[0] <> a[2] AND a[1] <> a[2] THEN
				RESULT = TRUE
				FOR l = 0 TO LENGTH(c) - 1
					IFB COPY(c[l], 1, 3) = JOIN(a, "") THEN
						RESULT = FALSE
						BREAK
					ENDIF
				NEXT
			ENDIF
			j = j + 1
		UNTIL RESULT OR (j > 100)
		IFB !RESULT THEN
			a[0] = 0
			a[1] = 0
			a[2] = 0
			MSGBOX("Error!")
		ENDIF
	ELSE
		RESULT = GetRandom(a, b, c, d)
	ENDIF
FEND

Alg同士の観戦等も可能です。