Add alt code to 2001/dgbeards + format README.md

The alt code is based on the author's notes. It makes it faster. I
discovered a fun flaw in the change and I challenge (in the alternate
code section) others to find it!

Format fix README.md.

Update bugs.md - this program deliberately crashes if it loses (which it
is tries to do). The author provided a way to fix it. It was uuencoded
but as per discussion on GitHub spoilers are not supposed to be here any
more so I uudecoded it. This feature was also added to the INABIAF
section in the README.md.

BTW: if you're trying to lose and you lose did win or did you lose? :-)
This commit is contained in:
Cody Boone Ferguson committed 2023-04-21 12:05:59 -07:00
1 parent 8ae3f6b6c6
commit fd5788f81c
5 files changed
+248 -61

No files matched your search

+1
View File
@@ -1 +1,2 @@
dgbeards dgbeards
dgbeards.alt
+2 -2
View File
@@ -115,8 +115,8 @@ OBJ= ${PROG}.o
DATA= DATA=
TARGET= ${PROG} TARGET= ${PROG}
# #
ALT_OBJ= ALT_OBJ= ${PROG}.alt.o
ALT_TARGET= ALT_TARGET= ${PROG}.alt
################# #################
+78 -59
View File
@@ -1,10 +1,10 @@
# Best AI # Best AI
Doug Beardsley Doug Beardsley
Southern Adventist University Southern Adventist University
359 Davis Rd. NW 359 Davis Rd. NW
Cleveland, TN 37312 Cleveland, TN 37312
USA USA
## To build: ## To build:
@@ -18,12 +18,31 @@ make
./dgbeards ./dgbeards
``` ```
## Try: ### Alternate code:
The author provided a way to speed it up a bit and also how to make it so it
doesn't crash on losing. [Cody Boone
Ferguson](/winners.html#Cody_Boone_Ferguson) made this alternate version with
the former change (the idea of crashing when losing is too good to fix in his
opinion). To compile:
```sh ```sh
echo "Do or do not. There is no try." make alt
``` ```
Use `dgbeards.alt` as you would `dgbeards` above. Can you find a flaw in this
version that the author did not note?
## INABIAF - it's not a bug it's a feature! :-)
This game crashes if it loses.
## Try:
See if you can figure out how to make the computer always lose. It's a very
simple thing to do. Read the author's remarks for clues.
## Judges' remarks: ## Judges' remarks:
This is probably the worst AI we've ever seen. So, then, why did This is probably the worst AI we've ever seen. So, then, why did
@@ -35,16 +54,19 @@ Of particular interest is the author's decision that the program should
crash if it loses. I've played chess with a lot of people like that, and crash if it loses. I've played chess with a lot of people like that, and
I appreciate the realism. I appreciate the realism.
BTW: if your goal is to lose and you do does that mean you win? :-) What does
winning mean in a game you're supposed to lose at?
## Author's remarks: ## Author's remarks:
FAQ: ### FAQ
Q: What does this program do? #### Q: What does this program do?
A: It lets the user play two player or single player games of suicide A: It lets the user play two player or single player games of [suicide
chess. Suicide Chess (also known as Losing Chess) is a variant of normal chess](https://en.wikipedia.org/wiki/Losing_chess). Suicide Chess (also known as
chess. It is played on the same board and uses the same pieces. Here is Losing Chess) is a variant of normal chess. It is played on the same board and
a list of the differences: uses the same pieces. Here is a list of the differences:
1. The object of the game is to get to a position where you have no legal 1. The object of the game is to get to a position where you have no legal
moves. This is usually accomplished by losing all of your pieces. moves. This is usually accomplished by losing all of your pieces.
@@ -66,36 +88,35 @@ can be captured.
5. Castling is not allowed. 5. Castling is not allowed.
Q: How do you use this program? #### Q: How do you use this program?
A: The program is fairly straightforward. When you start the program, A: The program is fairly straightforward. When you start the program,
it displays the opening position for a game of suicide chess and waits it displays the opening position for a game of suicide chess and waits
for user input. Commands are as follows: for user input. Commands are as follows:
quit - Quits the program - `quit` quits the program
g - Causes the computer to make a move - `g` causes the computer to make a move
Moves are represented by the long algebraic notation for the move. For Moves are represented by the long algebraic notation for the move. For those
those not familiar with long algebraic notation, a move consists of a not familiar with long algebraic notation, a move consists of a square to move
square to move from followed by a square to move to. Squares are denoted from followed by a square to move to. Squares are denoted by a letter and a
by a letter and a number. The letter specifies the column or file of the number. The letter specifies the column or file of the square and the number
square and the number specifies the row rank. Files are named from left specifies the row rank. Files are named from left to right by the letters `A` -
to right by the letters a-h. Rows are numbered from bottom to top with `H`. Rows are numbered from bottom to top with the numbers `1` - `8`. A sample
the numbers 1-8. A sample move from the opening position is e2e3. This move from the opening position is `E2E3`. This means to move a piece from
means to move a piece from square e2 to e3. From the opening position, square `E2` to `E3`. From the opening position, this corresponds to moving the
this corresponds to moving the king pawn forward one square. This is king pawn forward one square. This is generally to be considered one of the
generally to be considered one of the best opening moves in suicide best opening moves in suicide chess. All moves, captures and otherwise, are
chess. All moves, captures and otherwise, are represented with this represented with this notation. A special case is pawn promotion moves. They
notation. A special case is pawn promotion moves. They use the same use the same notation followed by an `=` and a letter representing the piece to
notation followed by an '=' and a letter representing the piece to promote to. The letters are `R`, `N` , `B`, `Q`, `K` representing rook, knight,
promote to. The letters are R,N,B,Q,K representing rook, knight, bishop, bishop, queen, and king respectively. The letters must be upper case.
queen, and king respectively. The letters must be upper case.
You can also specify a command line argument of a single digit to change You can also specify a command line argument of a single digit to change
the search depth of the program. If no argument is specified, it the search depth of the program. If no argument is specified, it
defaults to a depth of 3. defaults to a depth of 3.
Q: Are there any limitations in your program? #### Q: Are there any limitations in your program?
A: Yes. The first of the limitations is that you can only play legal A: Yes. The first of the limitations is that you can only play legal
moves according to the rules of suicide chess. En passant captures are moves according to the rules of suicide chess. En passant captures are
@@ -108,37 +129,38 @@ losses several moves ahead, but does not announce the end of a game or
the winner. Given the existing code it is easy to do this, but it was the winner. Given the existing code it is easy to do this, but it was
deemed unnecessary fluff. deemed unnecessary fluff.
Q: What is the playing strength of this program? #### Q: What is the playing strength of this program?
A: Playing strength is a relative term. Relative to other computer A: Playing strength is a relative term. Relative to other computer
programs that play suicide chess, it is about the bottom. There is one programs that play suicide chess, it is about the bottom. There is one
freeware program in existence called kenny that this program can beat, freeware program in existence called `kenny` that this program can beat,
but that is about it. but that is about it.
Suicide chess is a very tactical game. Most humans who do not have any Suicide chess is a very tactical game. Most humans who do not have any
experience in suicide chess will lose to this program. The Free Internet experience in suicide chess will lose to this program. The [Free Internet
Chess Server (http://www.freechess.org) is a free online chess server Chess Server](http://www.freechess.org) is a free online chess server
that supports suicide chess. This server keeps track of ratings. The that supports suicide chess. This server keeps track of ratings. The
human ratings for suicide chess range from 1000 to about 2400. This human ratings for suicide chess range from 1000 to about 2400. This
program would probably be rated somewhere around 1700-1900. It is better program would probably be rated somewhere around 1700-1900. It is better
than most players, but will get destroyed by experienced human opponents. than most players, but will get destroyed by experienced human opponents.
This program searches to a fixed depth of 3 ply. Because it does not This program searches to a fixed depth of 3
[ply](https://en.wikipedia.org/wiki/Ply_(game_theory)). Because it does not
search very deep, it performs very poorly in quiet strategic positions. search very deep, it performs very poorly in quiet strategic positions.
In such positions, it will often just shuffle pieces around aimlessly In such positions, it will often just shuffle pieces around aimlessly
until a tactical exchange presents itself. until a tactical exchange presents itself.
A small amount of randomness has been added to make the program a more A small amount of randomness has been added to make the program a more
interesting opponent. The to avoid a call to srand(), rand() and the interesting opponent. To avoid a call to `srand()`, `rand()` and the
extra code for the required include files, the time() function is used as extra code for the required include files, the `time()` function is used as
the source of random data. It is a slow function, and since it is the source of random data. It is a slow function, and since it is
executed inside the search loop, there is a significant performance executed inside the search loop, there is a significant performance
decrease. To make it faster, replace the time() call with rand() and add decrease. To make it faster, replace the `time()` call with `rand()` and add
the line srand(time(0)); to the beginning of main(). I used the more the line `srand(time(0));` to the beginning of `main()`. I used the more
inefficient time() function to illustrate a different (and somewhat inefficient `time()` function to illustrate a different (and somewhat
obfuscated?) way of generating random numbers. obfuscated?) way of generating random numbers.
Q: Why is this program obfuscated? #### Q: Why is this program obfuscated?
A: Here are several reasons: A: Here are several reasons:
@@ -168,7 +190,7 @@ penetrated by just preprocessing and beautifying the program.
Fifth, various small obfuscations have been used in places all over the Fifth, various small obfuscations have been used in places all over the
program. Short circuit evaluation is used as a substitute for if() program. Short circuit evaluation is used as a substitute for if()
statements in some places. The ternary operator is used. In the statements in some places. The ternary operator is used. In the
author's opinion, use of the ternary operator is almost always a strong author's opinion, use of the ternary operator is almost always a strong
argument for employee turnover. argument for employee turnover.
Last, if you have succeeded in wading through the previous layers of Last, if you have succeeded in wading through the previous layers of
@@ -177,36 +199,38 @@ implements is an obscure game. Casual inspection of the program might
lead one to believe that it is an implementation of classic chess, but lead one to believe that it is an implementation of classic chess, but
this is not so. this is not so.
Q: What about the compiler warnings? #### Q: What about the compiler warnings?
A: When compiled with gcc -Wall, the compiler generated the following A: When compiled with `gcc -Wall`, the compiler generated the following
warnings: warnings:
```
suggest parentheses around + or - in operand of & suggest parentheses around + or - in operand of &
array subscript has type 'char' array subscript has type 'char'
return type defaults to 'int' return type defaults to 'int'
control reaches end of non-void function control reaches end of non-void function
value computed is not used value computed is not used
```
The "value computed is not used" warning happens because I use the && The `value computed is not used` warning happens because I use the `&&`
operator and take advantage of short circuit evaluation instead of using operator and take advantage of short circuit evaluation instead of using
an if() statement. an if() statement.
The "suggest parentheses..." warnings are given because of expressions The `suggest parentheses...` warnings are given because of expressions
that depend on operator precedence details in the C language. that depend on operator precedence details in the C language.
Eliminating these warnings would reduce obfuscation. Eliminating these warnings would reduce obfuscation.
The other warnings are there because it would require more code to The other warnings are there because it would require more code to
eliminate them and that can't be done given the size limit. eliminate them and that can't be done given the size limit.
Q: Why does this program crash when it loses? #### Q: Why does this program crash when it loses?
A: What better way to admit defeat? The author thought this was A: What better way to admit defeat? The author thought this was
appropriate sportsmanship for a program of this genre and can think of appropriate sportsmanship for a program of this genre and can think of
no worse job than trying to find an elusive bug in an intentionally no worse job than trying to find an elusive bug in an intentionally
obfuscated program. obfuscated program.
[judge's note: This was followed by a description of the bug, and [Judge's note: This was followed by a description of the bug, and
the comment:] the comment:]
(Note, if this program wins, the author thinks it would be good to leave (Note, if this program wins, the author thinks it would be good to leave
@@ -214,16 +238,11 @@ this information out of the remarks and encourage others to try and
figure it out for themselves) figure it out for themselves)
[should you be too lazy to figure it out yourself, here's the author's [should you be too lazy to figure it out yourself, here's the author's
fix. I would have rot13'd it, but the punctuation would have survived.] fix.]
begin 644 fix.txt This bug can be fixed in a number of ways, but there is a way that adds only one
M5&AI<R!B=6<@8V%N(&)E(&9I>&5D(&EN(&$@;G5M8F5R(&]F('=A>7,L(&)U byte to the source code. In the statement `s=(e=-V(n-1,o))>s?Y=G,e:s;` change
M="!T:&5R90II<R!A('=A>2!T:&%T(&%D9',@;VYL>2!O;F4@8GET92!T;R!T the `>` to a `>=` and the bug will be gone.
M:&4@<V]U<F-E(&-O9&4N("!);B!T:&4@<W1A=&5M96YT"G,]*&4]+58H;BTQ
M+&\I*3YS/UD]1RQE.G,[(&-H86YG92!T:&4@/B!T;R!A(#X](&%N9"!T:&4@
38G5G('=I;&P@8F4@9V]N92X*"FYG
`
end
## Copyright and CC BY-SA 4.0 License: ## Copyright and CC BY-SA 4.0 License:
+163
View File
@@ -0,0 +1,163 @@
#include <stdio.h>
#include <string.h>
#include <time.h>
#define A(x,y) i[a++]=(N){c,c+x,y};
#define B(x,y) j[b++]=(N){c,c+x,y};
#define C(j,k) for (j=0; j<k; j++){
#define D(x) C(_,8)if(!(c+x[_]&136)){ if(p[c+x[_]]*p[c]<0)B(x[_],0)else if(!p[c+x[_]])A(x[_],0)} }
#define J printf(
#define O(v) _=v; while(!(c+_&136)){ x=p[c+_]*p[c]; if(x<0){B(_,0)E; } else if(x>0)E; else A(_,0)_+=v; }
#define X(x) G(x,L)
#define Z(x,y) memcpy(x,y,256);
typedef struct {
F a,b,c;
} N;
F g[]="KSLAU",
p[256],v[]="{ ; } ; { ; ; ; { } ; { ; } { ; } { } ; { ; ; ; { ; } ; } } ; { ; ; { } ; { } } ; { ; ; { { ; ; { } } ; } ; ; { } ; { } } ; { ; ; { { ; { } } ; { ; ; { } ; { { ; ; { } ; ; ; ; { ; } { { ; ; ; { } ; { ; ; ";
F S[]="{}; ",W[256],L[1024];
P q[]={-14,-31,-33,-18,14,31,33,18},r[]={-1,-17,-16,-15,1,17,16,15},_,a,b,c,d,e,t=1,x,y,z;
N i[500],j[500],*k,u;
P f(N *V) {
a=b=0;
C(d,8)
C(e,8)
c=d<<4|e;
if(p[c]==0||p[c]*t<0)continue;
switch(p[c]<0?-p[c]:p[c]){
K 80:
if(56+t*40==(c&112)&&!p[c-32*t])
A(t*-32,0)
if(56+t*-40==(c&112)){
if(!(c-17*t&136)&&p[c-17*t]*t<0){
C(_,5)
B(-17*t,(g[_]^_)*t)}
}
if(!(c-15*t&136)&&p[c-15*t]*t<0){
C(_,5)
B(-15*t,(g[_]^_)*t)}
}
C(_,5)
A(t*-16,(g[_]^_)*t)}
}else{
if(!p[c-16*t])
A(t*-16,0)
if(!(c-(17*t)&136)&&p[c-17*t]*t<0){
B(-17*t,0)
}
if(!(c-(15*t)&136)&&p[c-15*t]*t<0){
B(-15*t,0)
}
}
E;
K 78:D(q)E;
K 81:
K 66:O(17)O(-17)O(15)O(-15)
if(p[c]==66||p[c]==-66)
E;
K 82:O(1)O(-1)O(16)O(-16)E;
K 75:D(r)
} ;
}
}
if ( b > 0 ) {
C(_,b)V[_]=j[_]; }
R b;
} else {
C(_,a)V[_]=i[_]; }
R a;
}
}
F *G(F *n, F *o){
a=b=0;
for(; n[b]; d=0){
do{
d*=4;
d+=W[n[b++]];
} while(++b<8*a+8);
o[a++]=d;
}
o[a]=0;
R o;
}
m(N a){ p[a.b]=a.c?a.c:p[a.a]; p[a.a]=0; }
h(){
J X("{ ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; "));
c=0; C(c,120)c%8==0&&putchar(56-c/16);
if(p[c]<0){
J X("} { { ; { { { ; ; ; { ; } } } ; { "),-p[c]);
} else if(p[c]>0)
J X("} { { ; { { { ; } } } ; { { ; { { "),p[c]);
else
J"| ");
c%8==7?J X("} { { { ; ; { ; { { { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { ; } { ; } { ; } { ; ; { { ; ; ")),c+=8:0;
}
}
s() {
b=0; C(a,256)
if(v[b]==94){
b++; C(c,v[b]-32)p[a++]=v[b+1]-120;}
b+=2; a--;
} else
p[a]=v[b++]-120;
}
}
P w() {
P v=0;
C(_,120)
p[_]&&(p[_]*t>0&&v--,p[_]*t<0&&v++);
}
v+=f(i); v-=b?100:0;t=-t; v-=f(i); v+=b?100:0;t=-t;
R v;
}
P V(P n, P o) {
P s=-I,G,H,Y;
N M[500];
F u[256];
if(!(n+o))R w()+rand()%9-4;
if(!(H=f(M)))R I;
H<5?H==1?n++:(o<6?o++:0):0;
Z(u,p)
C(G,H)
Z(p,u)
m(M[G]);
t=-t;
s=(e=-V(n-1,o))>s?Y=G,e:s;
t=-t;
}
e=Y;
R s;
}
main(P db, F *bd[]){
srand(0);
N o[500];
F T[256];
C(a,256)W[a]=-1; }
C(a,4)W[S[a]]=a; }
G(v,v); s();
while(1){
h();
b=f(o);
scanf("%s",L);
if(strcmp(L,"quit")==0)R 0;
else if(strcmp(L,"g")==0){
Z(T,p)
J G("} } } ; } ; { } } ; { } } } } ; } } { ; { { { ; } } } ; } { { { ; ; ",L), V(db>1?atoi(bd[1]):3,0));
Z(p,T)m(o[e]); t=-t;
}else{
u.a=896-16*L[1];
u.b=896-16*L[3];
u.a+=L[0]-97;
u.b+=L[2]-97;
u.c=L[4]?L[5]:0;
C(a,b)
if(u.a==o[a].a&&u.b==o[a].b&&u.c==o[a].c)E;
}
a==b?J X("} { ; } } ; { } ; { } ; } } } ; } } ; { } } ; { { ; { { } ; } } ; } } ; } ; } } { { ; ; ")):(m(u),t=-t);
}
}
}
+4
View File
@@ -1049,6 +1049,10 @@ download and compile that version to test it - or it might not.
This program will very likely crash or do something different without an arg. This program will very likely crash or do something different without an arg.
## [2001/dgbeards](2001/dgbeards/dgbeards.c) ([README.md](2001/dgbeards/README.md))
## STATUS: INABIAF - please **DO NOT** fix
This program deliberately crashes if it loses (which is what it aims to do).
# 2002 # 2002