mirror of
https://github.com/abakh/nbsdgames.git
synced 2024-12-04 14:46:22 -05:00
Remove junk
This commit is contained in:
parent
e2bfedbee1
commit
6e29a11260
37
README.md
37
README.md
@ -1,37 +0,0 @@
|
||||
# New BSD Games
|
||||
|
||||
The TUI games i made for NetBSD ( If they accept these ).
|
||||
|
||||
These include:
|
||||
|
||||
Jewels (A game with a gameplay similiar to that of Tetris, NOT my invention)
|
||||
Sudoku
|
||||
Mines (Minesweeper)
|
||||
Reversi
|
||||
Checkers
|
||||
Battleship
|
||||
|
||||
### Prerequisites
|
||||
|
||||
ALL you need is a C compiler with C99 enabled , the standard library and libncurses (the dev package if you are on debian).
|
||||
|
||||
### How to run
|
||||
|
||||
Just download them somehow and compile them with ncurses being linked.
|
||||
|
||||
Normally:
|
||||
|
||||
```
|
||||
cc "address_to_sourcefiles/game_name.c" -lncurses -o "address_to_binaries/game_name"
|
||||
```
|
||||
|
||||
I am too lazy to write a script for this.
|
||||
|
||||
### How do these look like
|
||||
https://github.com/untakenstupidnick/new-bsd-games/blob/master/screenshot.png
|
||||
|
||||
### License
|
||||
|
||||
Public Domain.
|
||||
|
||||
I am living outside the Berne convention , This would be public domain anyway.
|
@ -1,560 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#define MISS -2
|
||||
#define SEA -1
|
||||
#define HIT 0
|
||||
#define ENGLISH_LETTERS 26
|
||||
#define NOTHING -1
|
||||
#define ALL 0x7c
|
||||
#define RED 3
|
||||
#define CYAN 2
|
||||
/*
|
||||
_
|
||||
|_)
|
||||
|_)ATTLESHIP
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
compile with -lncurses
|
||||
*/
|
||||
typedef signed char byte;
|
||||
typedef unsigned char bitbox;
|
||||
bool multiplayer;
|
||||
byte py,px;//cursor
|
||||
|
||||
chtype colors[4]={0};
|
||||
|
||||
byte game[2][10][10];//main board
|
||||
bool computer[2] = {0};
|
||||
byte score[2] = {0};//set by header()
|
||||
bitbox sunk[2]={0};
|
||||
byte just_sunk[2]={0};//to be displayed for human players
|
||||
|
||||
byte firstinrowy , firstinrowx ;
|
||||
byte lastinrowy ,lastinrowx;
|
||||
byte goindirection;
|
||||
byte shotinvain;
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
void rectangle(byte sy,byte sx){
|
||||
for(byte y=0;y<=10+1;y++){
|
||||
mvaddch(sy+y,sx,ACS_VLINE);
|
||||
mvaddch(sy+y,sx+10*2,ACS_VLINE);
|
||||
}
|
||||
for(byte x=0;x<=10*2;x++){
|
||||
mvaddch(sy,sx+x,ACS_HLINE);
|
||||
mvaddch(sy+10+1,sx+x,ACS_HLINE);
|
||||
}
|
||||
mvaddch(sy,sx,ACS_ULCORNER);
|
||||
mvaddch(sy+10+1,sx,ACS_LLCORNER);
|
||||
mvaddch(sy,sx+10*2,ACS_URCORNER);-
|
||||
mvaddch(sy+10+1,sx+10*2,ACS_LRCORNER);
|
||||
}
|
||||
void print_type(byte type){
|
||||
switch(type){
|
||||
case(2):
|
||||
addstr("patrol boat");
|
||||
break;
|
||||
case(3):
|
||||
addstr("destroyer");
|
||||
break;
|
||||
case(4):
|
||||
addstr("battleship");
|
||||
break;
|
||||
case(5):
|
||||
addstr("carrier");
|
||||
break;
|
||||
case(6):
|
||||
addstr("submarine");
|
||||
break;
|
||||
}
|
||||
}
|
||||
void MID(byte *y , byte *x, byte direction){
|
||||
switch(direction){
|
||||
case(0):
|
||||
*x=*x-1;
|
||||
break;
|
||||
case(1):
|
||||
*y=*y-1;
|
||||
break;
|
||||
case(2):
|
||||
*x=*x+1;
|
||||
break;
|
||||
case(3):
|
||||
*y=*y+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
void genocide(bool side , byte type){
|
||||
byte y,x;
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
if(game[side][y][x] == type)
|
||||
game[side][y][x] = SEA;
|
||||
}
|
||||
}
|
||||
}
|
||||
void header(bool side){
|
||||
score[0]=score[1]=0;
|
||||
byte y,x;
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
if(game[!side][y][x] == HIT)
|
||||
score[side]++;
|
||||
if(game[side][y][x] == HIT)
|
||||
score[!side]++;
|
||||
}
|
||||
}
|
||||
mvaddch(0,1, '_');
|
||||
mvprintw(1,0,"|_) %2d:%2d",score[side],score[!side]);
|
||||
mvprintw(2,0,"|_)ATTLESHIP ");
|
||||
}
|
||||
|
||||
void draw(bool side,byte sy,byte sx){//the game's board
|
||||
rectangle(sy,sx);
|
||||
chtype ch ;
|
||||
byte y,x;
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
ch =A_NORMAL;
|
||||
if(y==py && x==px)
|
||||
ch |= A_STANDOUT;
|
||||
if(game[side][y][x] == HIT)
|
||||
ch |= 'X'|colors[RED];
|
||||
else if(game[side][y][x] > 0 )
|
||||
ch |= ACS_BLOCK|colors[side];
|
||||
else if(game[side][y][x]== MISS)
|
||||
ch |= 'O'|colors[CYAN];
|
||||
else
|
||||
ch |= '~'|colors[CYAN];
|
||||
|
||||
mvaddch(sy+1+y,sx+x*2+1,ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
void draw_trackboard(bool side,byte sy,byte sx){
|
||||
rectangle(sy,sx);
|
||||
chtype ch ;
|
||||
byte y,x;
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
ch =A_NORMAL;
|
||||
if(y==py && x==px-10)
|
||||
ch |= A_STANDOUT;
|
||||
|
||||
if(game[!side][y][x] == HIT)
|
||||
ch |= '*'|colors[RED];
|
||||
else if(game[!side][y][x]== MISS)
|
||||
ch |= '~'|colors[CYAN];
|
||||
else
|
||||
ch |= '.';
|
||||
|
||||
mvaddch(sy+1+y,sx+x*2+1,ch);
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
void autoset(bool side){
|
||||
byte y=0,x=0,direction=0, invain=0;
|
||||
byte realy,realx;
|
||||
byte l;
|
||||
for(byte type=2;type<7;type++){
|
||||
SetLocation:
|
||||
realy=random()%10;
|
||||
realx=random()%10;
|
||||
invain=0;
|
||||
SetDirection:
|
||||
y=realy;
|
||||
x=realx;
|
||||
direction=random()%4;
|
||||
for(l=0;(type != 6 && l<type) || (type==6 && l<3) ; l++){//there are two kinds of ship sized 3 tiles
|
||||
if( y<0 || x<0 || y>=10 || x>=10 || game[side][y][x] != SEA ){
|
||||
genocide(side,type);
|
||||
invain++;
|
||||
direction= (direction+1)%4;
|
||||
if(invain<4)
|
||||
goto SetDirection;
|
||||
else
|
||||
goto SetLocation;//endless loop
|
||||
}
|
||||
else{
|
||||
game[side][y][x]=type;
|
||||
MID(&y,&x,direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void set_the_board(bool side){
|
||||
if( computer[side] ){
|
||||
autoset(side);
|
||||
return;
|
||||
}
|
||||
erase();
|
||||
mvaddch(0,1, '_');
|
||||
mvaddstr(1,0,"|_) Set your board");
|
||||
mvaddstr(2,0,"|_)ATTLESHIP");
|
||||
mvaddstr(16,0,"Press RETURN to specify the location and press R to rotate the ship.");
|
||||
int input;
|
||||
byte y=0,x=0,direction=0, invain=0;
|
||||
byte realy,realx;
|
||||
byte l;
|
||||
py=px=0;
|
||||
for(byte type=2;type<7;type++){
|
||||
mvaddstr(15,0,"Put your ");
|
||||
print_type(type);
|
||||
addstr(" in its position: ");
|
||||
SetLocation:
|
||||
while(1){
|
||||
draw(side,3,0);
|
||||
refresh();
|
||||
input = getch();
|
||||
if( (input=='k' || input==KEY_UP) && py>0)
|
||||
py--;
|
||||
if( (input=='j' || input==KEY_DOWN) && py<9)
|
||||
py++;
|
||||
if( (input=='h' || input==KEY_LEFT) && px>0)
|
||||
px--;
|
||||
if( (input=='l' || input==KEY_RIGHT) && px<9)
|
||||
px++;
|
||||
if( input=='\n' )
|
||||
break;
|
||||
if( input=='q' )
|
||||
sigint_handler(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
realy=y=py;
|
||||
realx=x=px;
|
||||
invain=0;
|
||||
SetDirection:
|
||||
y=realy;
|
||||
x=realx;
|
||||
for(l=0;(type != 6 && l<type) || (type==6 && l<3) ; l++){//there are two kinds of ship sized 3 tiles
|
||||
if( y<0 || x<0 || y>=10 || x>=10 || game[side][y][x] != SEA ){
|
||||
genocide(side,type);
|
||||
invain++;
|
||||
direction= (direction+1)%4;
|
||||
if(invain<4)
|
||||
goto SetDirection;
|
||||
else
|
||||
goto SetLocation;//endless loop
|
||||
}
|
||||
else{
|
||||
game[side][y][x]=type;
|
||||
MID(&y,&x,direction);
|
||||
}
|
||||
}
|
||||
while(1){
|
||||
invain=0;
|
||||
draw(side,3,0);
|
||||
input=getch();
|
||||
if( input== 'r' || input == 'R' ){
|
||||
genocide(side,type);
|
||||
direction= (direction+1)%4;
|
||||
goto SetDirection;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void turn_shift(void){
|
||||
if(!multiplayer)
|
||||
return;
|
||||
char key = 'a'+(random()%ENGLISH_LETTERS);
|
||||
int input1,input2,input3;
|
||||
input1=input2=input3=0;
|
||||
erase();
|
||||
beep();
|
||||
mvaddch(0,1, '_');
|
||||
mvaddstr(1,0,"|_) Anti-cheater");
|
||||
mvaddstr(2,0,"|_)ATTLESHIP");
|
||||
mvaddstr(4,0,"********************");
|
||||
mvprintw(5,0," Type '%c' 3 times ",key);
|
||||
mvaddstr(6,0," before ");
|
||||
mvaddstr(7,0," proceeding ");
|
||||
mvaddstr(8,0," to the game ");
|
||||
mvaddstr(10,0,"********************");
|
||||
refresh();
|
||||
while(1){
|
||||
input3=input2;
|
||||
input2=input1;
|
||||
input1=getch();
|
||||
if( (input1==input2) && (input2==input3) && (input3==key) )
|
||||
break;
|
||||
}
|
||||
erase();
|
||||
}
|
||||
byte shoot(bool turn, byte y , byte x){
|
||||
byte s = game[!turn][y][x];
|
||||
if(s>0){
|
||||
game[!turn][y][x]=HIT;
|
||||
return 1;
|
||||
}
|
||||
else if(s==HIT || s==MISS || y<0 || x<0 || y>9 || x>9 ){ //didn't shoot at all
|
||||
return -1;
|
||||
}
|
||||
else{
|
||||
game[!turn][y][x]=MISS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
void sink_announce(bool side){
|
||||
byte type,y,x;
|
||||
for(type=2;type<7;type++){
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
if( game[!side][y][x] == type )
|
||||
goto Next;
|
||||
}
|
||||
}
|
||||
//there is no instance of 'type' in the opponet's board
|
||||
if( ( (1 << type) | sunk[!side] ) != sunk[!side] ){
|
||||
sunk[!side] |= (1 << type);
|
||||
if(computer[side]){
|
||||
lastinrowy=lastinrowx=firstinrowy=firstinrowx=-1;
|
||||
shotinvain=0;
|
||||
}
|
||||
else{
|
||||
just_sunk[!side]=type;//leave to be displayed by you_sunk
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Next:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
void you_sunk(bool side){
|
||||
if( just_sunk[!side] == 3)
|
||||
mvaddstr(15,0,"You have destroyed my destroyer!!");
|
||||
else if( just_sunk[!side]){
|
||||
mvaddstr(15,0,"You have sunk my ");
|
||||
print_type(just_sunk[!side]);
|
||||
addstr("!!");
|
||||
}
|
||||
just_sunk[!side]=0;
|
||||
}
|
||||
void cheat(bool side){
|
||||
/* its actually an anti-cheat, the player can place all their ships adjacent to the others and in the same direction,
|
||||
and the algorithm will often play in a way that it will be left with some isolated tiles being unshot (with their ships being shot before).
|
||||
a human will *very easily* find the tiles with logical thinking, but the computer is random and it will take such a long time for it
|
||||
that it will often lose the winning game.
|
||||
|
||||
this function still doesn't make a win,it's randomly executed.*/
|
||||
byte y,x;
|
||||
for(y=0;y<10;y++){
|
||||
for(x=0;x<10;x++){
|
||||
if(game[!side][y][x]>0){
|
||||
shoot(side,y,x);
|
||||
firstinrowy=y;
|
||||
firstinrowx=x;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void decide(bool side){// sink_announce is responsible for unsetting this variables
|
||||
byte y,x,r;
|
||||
Again:
|
||||
if( firstinrowy == NOTHING ){
|
||||
if( score[!side] > 13 && score[side]<score[!side] && random()%2 ){
|
||||
cheat(side);
|
||||
return;
|
||||
}
|
||||
while(1){
|
||||
y = random()%10;
|
||||
x = random()%10;
|
||||
r = shoot(side,y,x);
|
||||
if(r == 1){
|
||||
firstinrowy=y;
|
||||
firstinrowx=x;
|
||||
}
|
||||
if(r != NOTHING)
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if( lastinrowy ==NOTHING ){
|
||||
if(goindirection == NOTHING)
|
||||
goindirection = random()%4;
|
||||
while(1){
|
||||
y= firstinrowy;
|
||||
x= firstinrowx;
|
||||
MID(&y,&x,goindirection);
|
||||
r= shoot(side,y,x);
|
||||
if( r != 1 ){
|
||||
goindirection = (goindirection+1)%4;
|
||||
|
||||
shotinvain++;
|
||||
if(shotinvain==4){ // this only occurs in case of a ship being shot before but not sunk ( e.g. in exprimenting for the direction)
|
||||
shotinvain=0;
|
||||
y=firstinrowy;
|
||||
x=firstinrowx;
|
||||
goindirection = (goindirection+1)%4;
|
||||
while(game[!side][y][x]==HIT){//go till you reach an unshot tile
|
||||
MID(&y,&x,goindirection);
|
||||
if( (y<0 || x<0 || y>9 || x>9) && r==NOTHING){
|
||||
goto Again;
|
||||
}
|
||||
}
|
||||
r= shoot(side,y,x);
|
||||
if(r==1){
|
||||
lastinrowy=y;//continue from the imaginary firstinrow
|
||||
lastinrowx=x;
|
||||
}
|
||||
if(r==NOTHING)
|
||||
goto Again;
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
lastinrowy= y;
|
||||
lastinrowx= x;
|
||||
}
|
||||
|
||||
if( r != NOTHING )
|
||||
return;
|
||||
}
|
||||
}
|
||||
else{
|
||||
y=lastinrowy;
|
||||
x=lastinrowx;
|
||||
MID(&y,&x,goindirection);
|
||||
r=shoot(side,y,x);
|
||||
if( r == 1 ){
|
||||
lastinrowy=y;
|
||||
lastinrowx=x;
|
||||
}
|
||||
else{
|
||||
lastinrowy=lastinrowx=NOTHING;
|
||||
goindirection=(goindirection+2)%4;
|
||||
}
|
||||
if( r != NOTHING )
|
||||
return;
|
||||
else{
|
||||
goto Again;
|
||||
}
|
||||
}
|
||||
}
|
||||
int main(int argc , char** argv){
|
||||
initscr();
|
||||
curs_set(0);
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr,1);
|
||||
if( has_colors() ){
|
||||
start_color();
|
||||
use_default_colors();
|
||||
init_pair(1,COLOR_GREEN,-1);
|
||||
init_pair(2,COLOR_YELLOW,-1);
|
||||
init_pair(3,COLOR_CYAN,-1);
|
||||
init_pair(4,COLOR_RED,-1);
|
||||
for(byte b=0;b<4;b++)
|
||||
colors[b]=COLOR_PAIR(b+1);
|
||||
}
|
||||
int input;
|
||||
printw("Choose type of the game:\n");
|
||||
printw("1 : Single Player*\n");
|
||||
printw("2 : Multi Player\n");
|
||||
input=getch();
|
||||
if(input == '2'){
|
||||
multiplayer=1;
|
||||
computer[1]=computer[0]=0;
|
||||
}
|
||||
else{
|
||||
multiplayer=0;
|
||||
computer[1]=1;
|
||||
computer[0]=0;
|
||||
}
|
||||
Start:
|
||||
firstinrowy=firstinrowx=lastinrowy=lastinrowx=goindirection=-1;
|
||||
shotinvain=0;
|
||||
sunk[0]=sunk[1]=0;
|
||||
memset(game,SEA,200);
|
||||
srandom(time(NULL)%UINT_MAX);
|
||||
erase();
|
||||
|
||||
set_the_board(0);
|
||||
turn_shift();
|
||||
set_the_board(1);
|
||||
bool won;
|
||||
bool turn=1;
|
||||
Turn:
|
||||
px=10;
|
||||
py=0;
|
||||
sink_announce(turn);
|
||||
if( sunk[0]==ALL ){
|
||||
won=1;
|
||||
goto End;
|
||||
}
|
||||
else if( sunk[1]==ALL ){
|
||||
won=0;
|
||||
goto End;
|
||||
}
|
||||
//the turn starts HERE
|
||||
turn=!turn;
|
||||
turn_shift();
|
||||
if( computer[turn] ){
|
||||
decide(turn);
|
||||
goto Turn;
|
||||
}
|
||||
else{
|
||||
erase();
|
||||
you_sunk(turn);
|
||||
while(1){
|
||||
header(turn);
|
||||
draw(turn,3,0);
|
||||
draw_trackboard(turn,3,22);
|
||||
refresh();
|
||||
input=getch();
|
||||
if( (input=='k' || input==KEY_UP) && py>0)
|
||||
py--;
|
||||
if( (input=='j' || input==KEY_DOWN) && py<9)
|
||||
py++;
|
||||
if( (input=='h' || input==KEY_LEFT) && px>10)
|
||||
px--;
|
||||
if( (input=='l' || input==KEY_RIGHT) && px<19)
|
||||
px++;
|
||||
if( input=='q')
|
||||
sigint_handler(EXIT_SUCCESS);
|
||||
if( input=='\n'){
|
||||
byte r=shoot(turn,py,px-10);
|
||||
if(r != -1){
|
||||
goto Turn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End:
|
||||
erase();
|
||||
header(won);
|
||||
draw(won,3,0);
|
||||
draw_trackboard(won,3,22);
|
||||
if( computer[won] )
|
||||
mvaddstr(15,0,"Hahaha! I won! ");
|
||||
else
|
||||
mvprintw(15,0,"Player %d won the game.",won+1);
|
||||
addstr(" Wanna play again? (y/N)");
|
||||
refresh();
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
if( input=='y' || input=='Y' ){
|
||||
curs_set(0);
|
||||
goto Start;
|
||||
}
|
||||
endwin();
|
||||
return 0;
|
||||
}
|
604
games/checkers.c
604
games/checkers.c
@ -1,604 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <math.h>
|
||||
#define LIGHT -1
|
||||
#define DARK 1
|
||||
#define KING 2
|
||||
#define DOESNT_MATTER 1
|
||||
#define IMAGINARY 0
|
||||
#define NORMAL 1
|
||||
#define ALT_IMG 2
|
||||
#define ALT_NRM 3
|
||||
#define WIN 100000
|
||||
/*
|
||||
.-.
|
||||
| '
|
||||
'._.HECKERS
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
|
||||
Compile with -lncurses
|
||||
*/
|
||||
typedef signed char byte;
|
||||
byte py,px;//cursor
|
||||
byte cy,cx;//selected(choosen) piece
|
||||
int dpt;
|
||||
byte game[8][8];
|
||||
byte computer[2]={0,0};
|
||||
byte score[2];//set by header()
|
||||
bool endgame=false;
|
||||
byte jumpagainy , jumpagainx;
|
||||
bool kinged;//if a piece jumps over multiple others and becomes a king it cannot continue jumping
|
||||
void rectangle(byte sy,byte sx){
|
||||
byte y,x;
|
||||
for(y=0;y<=8+1;y++){
|
||||
mvaddch(sy+y,sx,ACS_VLINE);
|
||||
mvaddch(sy+y,sx+8*2,ACS_VLINE);
|
||||
}
|
||||
for(x=0;x<=8*2;x++){
|
||||
mvaddch(sy,sx+x,ACS_HLINE);
|
||||
mvaddch(sy+8+1,sx+x,ACS_HLINE);
|
||||
}
|
||||
mvaddch(sy,sx,ACS_ULCORNER);
|
||||
mvaddch(sy+8+1,sx,ACS_LLCORNER);
|
||||
mvaddch(sy,sx+8*2,ACS_URCORNER);
|
||||
mvaddch(sy+8+1,sx+8*2,ACS_LRCORNER);
|
||||
}
|
||||
void header(void){
|
||||
score[0]=score[1]=0;
|
||||
byte y,x;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if(game[y][x]){
|
||||
if(game[y][x]<0)
|
||||
score[0]++;
|
||||
else
|
||||
score[1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mvprintw(0,0," .-.");
|
||||
mvprintw(1,0,"| ' %2d:%2d",score[0],score[1]);
|
||||
mvprintw(2,0,"'._,HECKERS ");
|
||||
}
|
||||
void draw(byte sy,byte sx){//the game's board
|
||||
rectangle(sy,sx);
|
||||
chtype ch ;
|
||||
byte y,x;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
ch=A_NORMAL;
|
||||
if(y==py && x==px)
|
||||
ch |= A_STANDOUT;
|
||||
if(y==cy && x==cx)
|
||||
ch |= A_BOLD;
|
||||
if(game[y][x]){
|
||||
if(game[y][x]<0){
|
||||
if(has_colors())
|
||||
ch|=COLOR_PAIR(1);
|
||||
else
|
||||
ch |= A_UNDERLINE;
|
||||
}
|
||||
if(abs(game[y][x])<2)
|
||||
ch |='O';
|
||||
else
|
||||
ch |='K';
|
||||
}
|
||||
else if( (y%2) != (x%2) )
|
||||
ch|='.';
|
||||
else
|
||||
ch|=' ';
|
||||
mvaddch(sy+1+y,sx+x*2+1,ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
void fill(void){
|
||||
byte y,x;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
game[y][x]=0;
|
||||
if( (y%2) != (x%2)){
|
||||
if(y<3) game[y][x]=1;
|
||||
if(y>4) game[y][x]=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool in(byte A[4],byte B[4],byte a,byte b){
|
||||
for(byte c=0;c<4;c++)
|
||||
if(A[c]==a && B[c]==b)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool moves(byte ty,byte tx,byte mvy[4],byte mvx[4]){
|
||||
bool ret=0;
|
||||
byte ndx=0;
|
||||
byte t= game[ty][tx];
|
||||
move(15,0);
|
||||
byte dy,dx;
|
||||
for(dy=-1;dy<2;dy++){
|
||||
for(dx=-1;dx<2;dx++){
|
||||
if( !dy || !dx || (!ty && dy<0) || (!tx && dx<0) || (dy==-t) || (ty+dy>=8) || (tx+dx>=8) )
|
||||
;
|
||||
else if(!game[ty+dy][tx+dx]){
|
||||
ret=1;
|
||||
mvy[ndx]=ty+dy;
|
||||
mvx[ndx]=tx+dx;
|
||||
ndx++;
|
||||
}
|
||||
else
|
||||
ndx++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
bool can_move(byte side){//would be much faster than applying moves() on every tile
|
||||
byte y , x ,t, dy , dx;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if( (t=game[y][x])*side > 0 ){
|
||||
for(dy=-1;dy<2;dy++){
|
||||
for(dx=-1;dx<2;dx++){
|
||||
if( !dy || !dx || (!y && dy<0) || (!x && dx<0) || (dy==-t) || (y+dy>=8) || (x+dx>=8) )
|
||||
;
|
||||
else if( !game[y+dy][x+dx] )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
bool jumps(byte ty,byte tx,byte mvy[4],byte mvx[4]){
|
||||
bool ret=0;
|
||||
byte ndx=0;
|
||||
byte ey,ex;
|
||||
byte t= game[ty][tx];
|
||||
byte dy,dx;
|
||||
for(dy=-1;dy<2;dy++){
|
||||
for(dx=-1;dx<2;dx++){
|
||||
ey = dy*2;
|
||||
ex = dx*2;
|
||||
if(!dy || !dx ||(dy==-t)|| (ty+ey<0) || (tx+ex<0) || (ty+ey>=8) || (tx+ex>=8) )
|
||||
;
|
||||
else if(!game[ty+ey][tx+ex] && game[ty+dy][tx+dx]*t<0){
|
||||
ret=1;
|
||||
mvy[ndx]=ty+ey;
|
||||
mvx[ndx]=tx+ex;
|
||||
ndx++;
|
||||
}
|
||||
else
|
||||
ndx++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
byte can_jump(byte ty,byte tx){
|
||||
byte dy,dx,t=game[ty][tx];
|
||||
byte ey,ex;
|
||||
byte ret=0;
|
||||
for(dy=-1;dy<2;dy++){
|
||||
for(dx=-1;dx<2;dx++){
|
||||
ey=dy*2;
|
||||
ex=dx*2;
|
||||
if((dy==-t)||(ty+ey<0)||(tx+ex<0)||(ty+ey>=8)||(tx+ex>=8) )
|
||||
;
|
||||
else if(!game[ty+dy*2][tx+dx*2]&&game[ty+dy][tx+dx]*t<0){
|
||||
ret++;
|
||||
if(ret>1)
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
byte forced_jump(byte side){
|
||||
byte y,x;
|
||||
byte foo,ret;
|
||||
foo=ret=0;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if(game[y][x]*side>0 && (foo=can_jump(y,x)) )
|
||||
ret+=foo;
|
||||
if(ret>1)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
byte cmove(byte fy,byte fx,byte sy,byte sx){//really move/jump , move is a curses function
|
||||
byte a = game[fy][fx];
|
||||
byte ret=0;
|
||||
game[fy][fx]=0;
|
||||
game[sy][sx]=a;
|
||||
if(abs(fy-sy) == 2){
|
||||
ret =game[(fy+sy)/2][(fx+sx)/2];
|
||||
game[(fy+sy)/2][(fx+sx)/2]=0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
bool king(byte y,byte x){
|
||||
byte t= (4-y)*game[y][x];
|
||||
if( (y==7 || !y) && t<0 && t>-5 ){
|
||||
game[y][x]*=2;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
double advantage(byte side){
|
||||
unsigned char own,opp;
|
||||
own=opp=0;
|
||||
byte foo;
|
||||
byte y,x;
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
foo=game[y][x]*side;
|
||||
if(foo>0){
|
||||
own++;//so it wont sacrfice two pawns for a king ( 2 kings == 3 pawns)
|
||||
own+=foo;
|
||||
}
|
||||
else if(foo<0){
|
||||
opp++;
|
||||
opp-=foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!own)
|
||||
return 0;
|
||||
else if(!opp)
|
||||
return WIN;
|
||||
else
|
||||
return (double)own/opp;
|
||||
}
|
||||
double posadvantage(byte side){
|
||||
double adv=0;
|
||||
double oppadv=0;
|
||||
byte foo;
|
||||
byte y,x;
|
||||
byte goal= (side>0)*7 , oppgoal=(side<0)*7;
|
||||
/*This encourages the AI to king its pawns and concentrate its kings in the center.
|
||||
The idea is : With forces in the center, movements to all of the board would be in the game tree horizon(given enough depth);
|
||||
and with forces being focused , its takes less movements to make an attack. */
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
foo=game[y][x]*side;
|
||||
if(foo>0){
|
||||
adv+=foo;
|
||||
adv++;
|
||||
if(foo==1)
|
||||
adv+= 1/( abs(y-goal) );//adding positional value
|
||||
else if(foo==2)
|
||||
adv+= 1/( fabs(y-3.5)+ fabs(x-3.5) );
|
||||
}
|
||||
else if( foo<0 ){
|
||||
oppadv-=foo;
|
||||
oppadv++;
|
||||
if(foo==-1)
|
||||
adv+=1/( abs(y-oppgoal) );
|
||||
else if(foo==-2)
|
||||
adv+= 1/( fabs(y-3.5)+ fabs(x-3.5) );
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!adv)
|
||||
return 0;
|
||||
else if( !oppadv )
|
||||
return WIN;
|
||||
else
|
||||
return adv/oppadv;
|
||||
return adv;
|
||||
}
|
||||
double decide(byte side,byte depth,byte s){
|
||||
byte fj=forced_jump(side);//only one legal jump if returns 1
|
||||
byte nextturn;
|
||||
|
||||
byte mvy[4],mvx[4];
|
||||
byte n;
|
||||
|
||||
bool didking;
|
||||
byte captured;
|
||||
|
||||
double adv=0;
|
||||
byte toy,tox;
|
||||
byte y,x;
|
||||
|
||||
double wrstadv=WIN+1;
|
||||
|
||||
double bestadv=0;
|
||||
byte besttoy,besttox;
|
||||
byte besty,bestx;
|
||||
bestx=besty=besttox=besttoy=-100;
|
||||
bool canmove=0;
|
||||
|
||||
byte nexts ;
|
||||
if(s == IMAGINARY || s == NORMAL )
|
||||
nexts=IMAGINARY;
|
||||
else
|
||||
nexts=ALT_IMG;
|
||||
|
||||
for(y=0;y<8;y++){
|
||||
for(x=0;x<8;x++){
|
||||
if(fj && (s==NORMAL || s==ALT_NRM) && jumpagainy>=0 && (jumpagainy!=y || jumpagainx!=x) )
|
||||
continue;
|
||||
if(game[y][x]*side>0){
|
||||
canmove=0;
|
||||
memset(mvy,-1,4);
|
||||
memset(mvx,-1,4);
|
||||
if(fj)
|
||||
canmove=jumps(y,x,mvy,mvx);
|
||||
else
|
||||
canmove=moves(y,x,mvy,mvx);
|
||||
if(canmove){
|
||||
for(n=0;n<4;n++){
|
||||
if(mvy[n] != -1){//a real move
|
||||
toy=mvy[n];
|
||||
tox=mvx[n];
|
||||
captured=cmove(y,x,toy,tox);//do the imaginary move
|
||||
if(fj && can_jump(toy,tox) ) //its a double jump
|
||||
nextturn=side;
|
||||
else
|
||||
nextturn=-side;
|
||||
didking=king(toy,tox);
|
||||
|
||||
//see the advantage you get
|
||||
if(fj==1 && (s==ALT_NRM || s==NORMAL) )
|
||||
adv= DOESNT_MATTER;
|
||||
else if(!depth){
|
||||
if(s==IMAGINARY || s==NORMAL)
|
||||
adv=advantage(side);
|
||||
else
|
||||
adv=posadvantage(side);
|
||||
}
|
||||
else{
|
||||
if(nextturn==side)
|
||||
adv=decide(nextturn,depth,nexts);
|
||||
else{
|
||||
adv=decide(nextturn,depth-!fj,nexts);
|
||||
if(adv==WIN)
|
||||
adv=0;
|
||||
else if(adv)
|
||||
adv=1/adv;
|
||||
else
|
||||
adv=WIN;
|
||||
}
|
||||
}
|
||||
//undo the imaginary move
|
||||
if(didking)
|
||||
game[toy][tox]/=2;
|
||||
game[y][x]=game[toy][tox];
|
||||
game[toy][tox]=0;
|
||||
if(fj)
|
||||
game[(toy+y)/2][(tox+x)/2]=captured;
|
||||
|
||||
if(besty<0 || adv>bestadv || (adv==bestadv && ( random()%2 )) ){
|
||||
besty=y;
|
||||
bestx=x;
|
||||
besttoy=toy;
|
||||
besttox=tox;
|
||||
bestadv=adv;
|
||||
}
|
||||
if(adv<wrstadv)
|
||||
wrstadv=adv;
|
||||
if(fj == 1)
|
||||
goto EndLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EndLoop:
|
||||
if( (s==NORMAL || s==ALT_NRM) && besty >= 0 ){
|
||||
if(endgame && fj!=1 && s==NORMAL && bestadv==wrstadv ){
|
||||
if(wrstadv == WIN){//the randomization in the algorithm may cause an illusion of inevitable win
|
||||
if(depth > 1)
|
||||
decide(side,depth-1,NORMAL);
|
||||
else
|
||||
goto Move;
|
||||
}
|
||||
else
|
||||
decide(side,depth,ALT_NRM);
|
||||
}
|
||||
else{
|
||||
Move:
|
||||
cmove(besty,bestx,besttoy,besttox);
|
||||
kinged=king(besttoy,besttox);
|
||||
if(!kinged && can_jump(besttoy,besttox) ){
|
||||
jumpagainy = besttoy;
|
||||
jumpagainx = besttox;
|
||||
}
|
||||
else
|
||||
jumpagainy=jumpagainx=-1;
|
||||
}
|
||||
}
|
||||
return bestadv;
|
||||
}
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
int main(int argc,char** argv){
|
||||
dpt=3;
|
||||
if(argc>2){
|
||||
printf("Usage: %s [AIpower]\n",argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(argc==2){
|
||||
if(sscanf(argv[1],"%d",&dpt) && dpt<128 && dpt>0)
|
||||
;
|
||||
else{
|
||||
puts("That should be a number from 1 to 127.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr,1);
|
||||
int input ;
|
||||
printw("Black plays first.\n Choose type of the black player(H/c)\n" );
|
||||
input=getch();
|
||||
if(input=='c'){
|
||||
computer[0]=dpt;
|
||||
printw("Computer.\n");
|
||||
}
|
||||
else{
|
||||
computer[0]=0;
|
||||
printw("Human.\n");
|
||||
}
|
||||
printw("Choose type of the white player(h/C)\n");
|
||||
input=getch();
|
||||
if(input=='h'){
|
||||
computer[1]=0;
|
||||
printw("Human.\n");
|
||||
}
|
||||
else{
|
||||
computer[1]=dpt;
|
||||
printw("Computer.\n");
|
||||
}
|
||||
if(has_colors()){
|
||||
start_color();
|
||||
use_default_colors();
|
||||
init_pair(1,COLOR_RED,-1);
|
||||
}
|
||||
signal(SIGINT,sigint_handler);
|
||||
Start:
|
||||
srandom(time(NULL)%UINT_MAX);
|
||||
fill();
|
||||
cy=cx=-1;
|
||||
py=px=0;
|
||||
byte mvy[4],mvx[4];
|
||||
memset(mvy,-1,4);
|
||||
memset(mvx,-1,4);
|
||||
byte turn=1;
|
||||
bool t=1;
|
||||
bool fj;
|
||||
byte result;
|
||||
byte todraw=0;
|
||||
double adv = 1;//used to determine when the game is a draw
|
||||
double previousadv =1;
|
||||
Turn:
|
||||
jumpagainy=jumpagainx=-1;
|
||||
kinged=0;
|
||||
turn =-turn;
|
||||
t=!t;//t == turn<0 that's turn in binary/array index format
|
||||
fj = forced_jump(turn);
|
||||
erase();
|
||||
flushinp();
|
||||
header();
|
||||
draw(3,0);
|
||||
if(t){
|
||||
previousadv=adv;
|
||||
adv= advantage(1) + (score[0]*score[1]);//just taking the dry scores to account too,nothing special
|
||||
if(previousadv==adv)
|
||||
todraw++;
|
||||
else
|
||||
todraw=0;
|
||||
}
|
||||
if(!score[0] || (turn==-1 && !fj && !can_move(-1))){
|
||||
result=1;
|
||||
goto End;
|
||||
}
|
||||
else if(!score[1] || (turn==1 && !fj && !can_move(1))){
|
||||
result=-1;
|
||||
goto End;
|
||||
}
|
||||
else if(todraw==50){ // 50 turns without any gained advantage for each side
|
||||
result=0;
|
||||
goto End;
|
||||
}
|
||||
endgame= score[t]<=5 || score[!t]<=5;
|
||||
draw(3,0);
|
||||
refresh();
|
||||
while(computer[t]){
|
||||
mvprintw(13,0,"Thinking...");
|
||||
refresh();
|
||||
computer[t]=dpt+ (score[!t] != score[t]) + endgame;
|
||||
decide(turn,computer[t],1);
|
||||
if(!(fj && jumpagainy>=0 && !kinged )){
|
||||
goto Turn;
|
||||
}
|
||||
}
|
||||
while(1){
|
||||
erase();
|
||||
draw(3,0);
|
||||
header();
|
||||
refresh();
|
||||
input=getch();
|
||||
if( (input=='k' || input==KEY_UP) && py>0)
|
||||
py--;
|
||||
if( (input=='j' || input==KEY_DOWN) && py<7)
|
||||
py++;
|
||||
if( (input=='h' || input==KEY_LEFT) && px>0)
|
||||
px--;
|
||||
if( (input=='l' || input==KEY_RIGHT) && px<7)
|
||||
px++;
|
||||
if( input=='q'){
|
||||
result=2;
|
||||
goto End;
|
||||
}
|
||||
if(input=='\n'){
|
||||
if(game[py][px]*turn>0){
|
||||
cy=py;
|
||||
cx=px;
|
||||
memset(mvy,-1,4);
|
||||
memset(mvx,-1,4);
|
||||
if(!fj)
|
||||
moves(py,px,mvy,mvx);
|
||||
jumps(py,px,mvy,mvx);
|
||||
}
|
||||
if( in(mvy,mvx,py,px) && !(jumpagainy>=0 && (cy !=jumpagainy || cx != jumpagainx) ) ){
|
||||
memset(mvy,-1,4);
|
||||
memset(mvx,-1,4);
|
||||
cmove(cy,cx,py,px);
|
||||
kinged=king(py,px);
|
||||
cy=-1;
|
||||
cx=-1;
|
||||
if( !(fj && can_jump(py,px) && !kinged ) ){
|
||||
goto Turn;
|
||||
}
|
||||
else{
|
||||
jumpagainy=py;
|
||||
jumpagainx=px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
End:
|
||||
move(13,0);
|
||||
switch(result){
|
||||
case -1:
|
||||
printw("The black side has won the game.");
|
||||
break;
|
||||
case 0:
|
||||
printw("Draw.");
|
||||
break;
|
||||
case 1:
|
||||
printw("The white side has won the game.");
|
||||
break;
|
||||
case 2:
|
||||
printw("You resigned.");
|
||||
}
|
||||
printw(" Wanna rematch?(y/N)");
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
if(input=='y' || input=='Y'){
|
||||
byte b=computer[0];
|
||||
computer[0]=computer[1];
|
||||
computer[1]=b;
|
||||
goto Start;
|
||||
}
|
||||
endwin();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
365
games/jewels.c
365
games/jewels.c
@ -1,365 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#define LEN 17
|
||||
#define WID 19
|
||||
#define DELAY 2
|
||||
#define SAVE_TO_NUM 10
|
||||
#define DEF_ADDRESS "JewelScores"
|
||||
|
||||
/*
|
||||
Jewels
|
||||
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
compile with -lnucrses
|
||||
|
||||
A pair of jewels appear on top of the window, And you can move and rotate them while they are falling down.
|
||||
If you make a vertical or horizontal row of 4 jewels they will explode and add up to your score.
|
||||
Like Tetris,You will lose the game when the center of the uppermost row is filled.
|
||||
*/
|
||||
|
||||
typedef signed char byte;
|
||||
chtype board[LEN][WID];
|
||||
byte jx,jy; //first jewel's position
|
||||
byte kx,ky;//second jewel's position in relation to that of j
|
||||
long score=0;
|
||||
char* controls = "j,l-Move k-Rotate p-Pause q-Quit";
|
||||
FILE* scorefile;
|
||||
byte scorewrite(long score){// only saves the top 10
|
||||
bool deforno;
|
||||
if( !getenv("JW_SCORES") && (scorefile= fopen(DEF_ADDRESS,"r")) ){
|
||||
deforno=1;
|
||||
}
|
||||
else{
|
||||
deforno=0;
|
||||
if( !(scorefile = fopen(getenv("JW_SCORES"),"r")) ){
|
||||
printf("\nNo accessible score files found.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
char namebuff[SAVE_TO_NUM][60];
|
||||
long scorebuff[SAVE_TO_NUM];
|
||||
|
||||
memset(namebuff,0,SAVE_TO_NUM*60*sizeof(char) );
|
||||
memset(scorebuff,0,SAVE_TO_NUM*sizeof(long) );
|
||||
|
||||
long fuckingscore =0;
|
||||
char fuckingname[60]={0};
|
||||
byte location=0;
|
||||
|
||||
while( fscanf(scorefile,"%59s : %ld\n",fuckingname,&fuckingscore) == 2 && location<SAVE_TO_NUM ){
|
||||
strcpy(namebuff[location],fuckingname);
|
||||
scorebuff[location] = fuckingscore;
|
||||
location++;
|
||||
|
||||
memset(fuckingname,0,60);
|
||||
fuckingscore=0;
|
||||
}
|
||||
if(deforno)
|
||||
scorefile = fopen(DEF_ADDRESS,"w+");//get rid of the text
|
||||
else
|
||||
scorefile = fopen(getenv("JW_SCORES"), "w+") ;
|
||||
if(!scorefile){
|
||||
printf("\nThe file cannot be opened in w+.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
byte itreached=location;
|
||||
byte ret = -1;
|
||||
bool wroteit=0;
|
||||
|
||||
for(location=0;location<=itreached && location<SAVE_TO_NUM-wroteit;location++){
|
||||
if(!wroteit && (location>=itreached || score>=scorebuff[location]) ){
|
||||
fprintf(scorefile,"%s : %ld\n",getenv("USER"),score);
|
||||
ret=location;
|
||||
wroteit=1;
|
||||
}
|
||||
if(location<SAVE_TO_NUM-wroteit && location<itreached)
|
||||
fprintf(scorefile,"%s : %ld\n",namebuff[location],scorebuff[location]);
|
||||
}
|
||||
fflush(scorefile);
|
||||
return ret;
|
||||
}
|
||||
void showscores(byte playerrank){
|
||||
if(playerrank == 0){
|
||||
char formername[60]={0};
|
||||
long formerscore=0;
|
||||
rewind(scorefile);
|
||||
fscanf(scorefile,"%*s : %*d\n");
|
||||
if ( fscanf(scorefile,"%s : %ld\n",formername,&formerscore)==2){
|
||||
printf("\n****CONRAGULATIONS!***\n");
|
||||
printf(" _____ You bet the\n");
|
||||
printf(" .' | previous\n");
|
||||
printf(" .' | record\n");
|
||||
printf(" | .| | of\n");
|
||||
printf(" |.' | |%11ld\n",formerscore);
|
||||
printf(" | | held by\n");
|
||||
printf(" ___| |___%8s\n",formername);
|
||||
printf(" | |\n");
|
||||
printf(" |____________|\n");
|
||||
printf("**********************\n");
|
||||
}
|
||||
|
||||
}
|
||||
//scorefile is still open with w+
|
||||
char pname[60] = {0};
|
||||
long pscore=0;
|
||||
byte rank=0;
|
||||
rewind(scorefile);
|
||||
printf("\n>*>*>Top %d<*<*<\n",SAVE_TO_NUM);
|
||||
while( rank<SAVE_TO_NUM && fscanf(scorefile,"%s : %ld\n",pname,&pscore) == 2){
|
||||
if(rank == playerrank)
|
||||
printf(">>>");
|
||||
printf("%d) %s : %ld\n",rank+1,pname,pscore);
|
||||
rank++;
|
||||
}
|
||||
putchar('\n');
|
||||
|
||||
}
|
||||
//apply gravity
|
||||
bool fall(void){
|
||||
bool jfall,kfall,ret;
|
||||
jfall=kfall=ret=0;
|
||||
for(int y=LEN-1;y>0;y--){
|
||||
chtype c,d;
|
||||
for(int x=WID-1;x>=0;x--){
|
||||
c=board[y][x];
|
||||
d=board[y-1][x];
|
||||
if(!c && d){
|
||||
board[y-1][x]=0;
|
||||
board[y][x]=d;
|
||||
if(y-1==jy && x==jx)
|
||||
jfall=1;
|
||||
if((y-1==jy+ky) && (x==jx+kx))
|
||||
kfall=1;
|
||||
ret=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(jfall&&kfall)
|
||||
jy++;
|
||||
else
|
||||
jy = LEN+1;
|
||||
return ret;
|
||||
}
|
||||
// rotate 90d clockwise in ky/x format
|
||||
void clockwise(byte* y,byte* x){
|
||||
/*
|
||||
o x
|
||||
x xo o ox*/
|
||||
chtype fx,fy;
|
||||
if(*y)
|
||||
fy=0;
|
||||
fx=-*y;
|
||||
|
||||
if(*x)
|
||||
fx=0;
|
||||
fy=*x;
|
||||
*y=fy;
|
||||
*x=fx;
|
||||
}
|
||||
|
||||
//rtt jwls
|
||||
bool rotate(void){//f:future
|
||||
if(jy>LEN)
|
||||
return 0;
|
||||
byte fy,fx;
|
||||
fy=ky;fx=kx;
|
||||
clockwise(&fy,&fx);
|
||||
if( jy+fy<0 || jy+fy>=LEN || jx+fx<0 || jx+fx>=WID )
|
||||
return 0;
|
||||
if(board[jy+fy][jx+fx])
|
||||
return 0;
|
||||
chtype a = board[jy+ky][jx+kx];
|
||||
board[jy+ky][jx+kx]=0;
|
||||
ky=fy;
|
||||
kx=fx;
|
||||
board[jy+ky][jx+kx]=a;
|
||||
return 1;
|
||||
}
|
||||
//mv jwls
|
||||
bool jmove(byte dy,byte dx){
|
||||
if(jy>LEN)
|
||||
return 0;
|
||||
|
||||
if(jx+dx>=WID || jx+dx<0 || jx+kx+dx>=WID ||jx+kx+dx<0 || jy+dx<0 ||jx+dx+kx<0)
|
||||
return 0;
|
||||
if( board[jy+ky+dy][jx+kx+dx] )
|
||||
if( !(jy+ky+dy == jy && jx+kx+dx==jx) )
|
||||
return 0;
|
||||
|
||||
if( board[jy+dy][jx+dx])
|
||||
if(!(dx==kx && dy==ky))
|
||||
return 0;
|
||||
//still alive?
|
||||
chtype a = board[jy][jx];
|
||||
chtype b = board[jy+ky][jx+kx];
|
||||
board[jy][jx]=0;
|
||||
board[jy+ky][jx+kx]=0;
|
||||
board[jy+dy][jx+dx]=a;
|
||||
board[jy+ky+dy][jx+kx+dx]=b;
|
||||
jy+=dy;jx+=dx;
|
||||
return 1;
|
||||
}
|
||||
//scoring algorithm
|
||||
bool explode(void){
|
||||
bool ret =0;
|
||||
chtype c,uc;
|
||||
byte n;
|
||||
byte y,x;
|
||||
for(y=0;y<LEN;y++){
|
||||
c=uc=n=0;
|
||||
for(byte x=0;x<WID;x++){
|
||||
uc = c;
|
||||
c = board[y][x];
|
||||
if(c && c == uc)
|
||||
n++;
|
||||
else
|
||||
n=0;
|
||||
if(n==3){
|
||||
ret=1;
|
||||
for(;n>=0;n--)
|
||||
board[y][x-n]=0;
|
||||
n=0;
|
||||
score+=30;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(x=0;x<WID;x++){
|
||||
c=uc=n=0;
|
||||
for(byte y=0;y<LEN;y++){
|
||||
uc=c;
|
||||
c = board[y][x];
|
||||
if(c && c==uc)
|
||||
n++;
|
||||
else
|
||||
n=0;
|
||||
if(n==3){
|
||||
ret=1;
|
||||
for(;n>=0;n--)
|
||||
board[y-n][x]=0;
|
||||
n=0;
|
||||
score+=30;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//display
|
||||
void draw(void){
|
||||
erase();
|
||||
int middle = (COLS/2-1)-(WID/2);
|
||||
chtype a=A_STANDOUT|' ';
|
||||
mvhline(LEN,middle-2,a,WID+4);
|
||||
mvvline(0,middle-1,a,LEN);
|
||||
mvvline(0,middle-2,a,LEN);
|
||||
mvvline(0,middle+WID,a,LEN);
|
||||
mvvline(0,middle+WID+1,a,LEN);
|
||||
mvprintw(0,0,"Score:%d",score);
|
||||
for(byte y=0;y<LEN;y++){
|
||||
for(byte x=0;x<WID;x++){
|
||||
chtype c = board[y][x];
|
||||
if(c)
|
||||
mvaddch(y,middle+x,c);
|
||||
}
|
||||
}
|
||||
mvaddstr(LINES-2,middle-5,controls);
|
||||
refresh();
|
||||
}
|
||||
int main(void){
|
||||
initscr();
|
||||
cbreak();
|
||||
halfdelay(DELAY);
|
||||
noecho();
|
||||
curs_set(0);
|
||||
wnoutrefresh(stdscr);
|
||||
int input;
|
||||
bool falls;
|
||||
byte stop=0;
|
||||
char jwstr[] = {'*','^','~','"','$','V'};
|
||||
chtype colors[6]={0};
|
||||
if(has_colors()){
|
||||
start_color();
|
||||
use_default_colors();
|
||||
init_pair(1,COLOR_RED,-1);
|
||||
init_pair(2,COLOR_GREEN,-1);
|
||||
init_pair(3,COLOR_MAGENTA,-1);
|
||||
init_pair(4,COLOR_BLUE,-1);//array this thing
|
||||
init_pair(5,COLOR_YELLOW,-1);
|
||||
init_pair(6,COLOR_CYAN,-1);
|
||||
for(byte n=0;n<5;n++){
|
||||
colors[n] = COLOR_PAIR(n+1);
|
||||
}
|
||||
}
|
||||
|
||||
srandom(time(NULL)%UINT_MAX);
|
||||
while(1){
|
||||
chtype a,b;
|
||||
a=board[0][WID/2];
|
||||
b=board[0][WID/2-1];
|
||||
if(a || b ){
|
||||
goto Lose;
|
||||
}
|
||||
jy=ky=0;
|
||||
jx=WID/2;
|
||||
kx=-1;
|
||||
byte ran1= random()%5;
|
||||
byte ran2= random()%5;
|
||||
board[jy][jx]=colors[ran1]|jwstr[ran1];
|
||||
board[jy+ky][jx+kx]=colors[ran2]|jwstr[ran2];
|
||||
falls = 1;
|
||||
while(falls){
|
||||
input = getch();
|
||||
|
||||
if(input != ERR)
|
||||
stop+=1;
|
||||
|
||||
if( stop >= 10){
|
||||
falls=fall();
|
||||
stop=0;
|
||||
}
|
||||
else if(input=='l')
|
||||
jmove(0,+1);
|
||||
else if(input=='j')
|
||||
jmove(0,-1);
|
||||
else if(input=='k')
|
||||
rotate();
|
||||
else if(input=='p'){
|
||||
mvaddstr(LINES-2,COLS/2-15,"Paused - Press a key to continue ");
|
||||
refresh();
|
||||
nocbreak();
|
||||
cbreak();
|
||||
getch();
|
||||
halfdelay(DELAY);
|
||||
}
|
||||
else if(input=='q')
|
||||
goto Lose;
|
||||
else if(input==' ')
|
||||
while( (falls=fall()) )
|
||||
stop=0;
|
||||
else{
|
||||
falls=fall();
|
||||
stop=0;
|
||||
}
|
||||
draw();
|
||||
}
|
||||
while(explode()){ // explode, fall, explode, fall until nothing is left
|
||||
while(fall());
|
||||
draw();
|
||||
}
|
||||
}
|
||||
Lose:
|
||||
nocbreak();
|
||||
endwin();
|
||||
printf("%s _Jewels_ %s\n",jwstr,jwstr);
|
||||
printf("You have scored %ld points.\n",score);
|
||||
showscores(scorewrite(score));
|
||||
return EXIT_SUCCESS;
|
||||
}
|
266
games/mines.c
266
games/mines.c
@ -1,266 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
/*
|
||||
|\/|
|
||||
| |INES
|
||||
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
compile with -lncurses
|
||||
*/
|
||||
typedef signed char byte;
|
||||
int len,wid,py,px;
|
||||
int untouched;
|
||||
int mscount;
|
||||
chtype colors[6]={0};
|
||||
void rectangle(int sy,int sx){
|
||||
for(int y=0;y<=len+1;y++){
|
||||
mvaddch(sy+y,sx,ACS_VLINE);
|
||||
mvaddch(sy+y,sx+wid*2,ACS_VLINE);
|
||||
}
|
||||
for(int x=0;x<=wid*2;x++){
|
||||
mvaddch(sy,sx+x,ACS_HLINE);
|
||||
mvaddch(sy+len+1,sx+x,ACS_HLINE);
|
||||
}
|
||||
mvaddch(sy,sx,ACS_ULCORNER);
|
||||
mvaddch(sy+len+1,sx,ACS_LLCORNER);
|
||||
mvaddch(sy,sx+wid*2,ACS_URCORNER);
|
||||
mvaddch(sy+len+1,sx+wid*2,ACS_LRCORNER);
|
||||
}
|
||||
|
||||
void draw(int sy,int sx,byte board[len][wid]){
|
||||
rectangle(sy,sx);
|
||||
chtype attr ;
|
||||
char prnt;
|
||||
int y,x;
|
||||
for(y=0;y<len;y++){
|
||||
for(x=0;x<wid;x++){
|
||||
attr=A_NORMAL;
|
||||
if(y==py && x==px)
|
||||
attr |= A_STANDOUT;
|
||||
|
||||
if(board[y][x]<0)
|
||||
prnt='.';
|
||||
else if(!board[y][x])
|
||||
prnt=' ';
|
||||
else if(board[y][x] < 8){
|
||||
attr |= colors[board[y][x]-1];
|
||||
prnt='0'+board[y][x];
|
||||
}
|
||||
else if(board[y][x]==9){
|
||||
attr |= colors[3];
|
||||
prnt='P';
|
||||
}
|
||||
else if(board[y][x]>9)
|
||||
prnt='?';
|
||||
|
||||
mvaddch(sy+1+y,sx+x*2+1,attr|prnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
void drawmines(int sy,int sx,byte board[len][wid],bool mines[len][wid]){
|
||||
int y,x;
|
||||
for(y=0;y<len;y++){
|
||||
for(x=0;x<wid;x++){
|
||||
if(mines[y][x]){
|
||||
if(y==py&&x==px)
|
||||
mvaddch(sy+y+1,sx+x*2+1,'X');
|
||||
else if(board[y][x]==9)
|
||||
mvaddch(sy+y+1,sx+x*2+1,'%');
|
||||
else
|
||||
mvaddch(sy+y+1,sx+x*2+1,'*');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void mine(bool mines[len][wid]){
|
||||
int y=random()%len;
|
||||
int x=random()%wid;
|
||||
for(int n=0;n<mscount;n++){
|
||||
while(mines[y][x]){
|
||||
y=random()%len;
|
||||
x=random()%wid;
|
||||
}
|
||||
mines[y][x]=true;
|
||||
}
|
||||
}
|
||||
|
||||
bool click(byte board[len][wid],bool mines[len][wid],int ty,int tx){
|
||||
if(board[ty][tx]>=0 && board[ty][tx] <9)
|
||||
return 0;
|
||||
|
||||
if(board[ty][tx]<0 || board[ty][tx]>8){//untouched
|
||||
board[ty][tx]=0;
|
||||
untouched--;
|
||||
}
|
||||
int y,x;
|
||||
for(y=ty-1;y<ty+2;y++){
|
||||
if(y<0)
|
||||
y=0;
|
||||
if(y>=len)
|
||||
break;
|
||||
for (x=tx-1;x<tx+2;x++){
|
||||
if(x<0)
|
||||
x=0;
|
||||
if(x>=wid)
|
||||
break;
|
||||
|
||||
if(mines[y][x])
|
||||
board[ty][tx]++;
|
||||
}
|
||||
}
|
||||
|
||||
if(!board[ty][tx]){
|
||||
for(y=ty-1;y<ty+2;y++){
|
||||
if(y<0)
|
||||
y=0;
|
||||
if(y>=len)
|
||||
break;
|
||||
for(x=tx-1;x<tx+2;x++){
|
||||
if(x<0)
|
||||
x=0;
|
||||
if(x>=wid)
|
||||
break;
|
||||
|
||||
click(board,mines,y,x);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
int main(int argc, char** argv){
|
||||
signal(SIGINT,sigint_handler);
|
||||
if(argc>4 || (argc==2 && !strcmp("help",argv[1])) ){
|
||||
printf("Usage: %s [len wid [minescount]]\n",argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(argc==2){
|
||||
puts("Give both dimensions.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(argc>=3){
|
||||
bool lool = sscanf(argv[1],"%d",&len) && sscanf(argv[2],"%d",&wid);
|
||||
if(!lool){
|
||||
puts("Invalid input.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(len<5 || wid<5 || len>1000 || wid>1000){
|
||||
puts("At least one of your given dimensions is too small or too big.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
len=wid=8;
|
||||
if(argc==4){
|
||||
if( !sscanf(argv[3],"%d",&mscount)){
|
||||
puts("Invalid input.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if( mscount<5 || mscount>= len*wid){
|
||||
puts("Too few/many mines.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
mscount = len*wid/6;
|
||||
srandom(time(NULL)%UINT_MAX);
|
||||
Start:
|
||||
initscr();
|
||||
curs_set(0);
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr,1);
|
||||
if(has_colors()){
|
||||
start_color();
|
||||
use_default_colors();
|
||||
init_pair(1,COLOR_BLUE,-1);
|
||||
init_pair(2,COLOR_GREEN,-1);
|
||||
init_pair(3,COLOR_YELLOW,-1);
|
||||
init_pair(4,COLOR_RED,-1);
|
||||
init_pair(5,COLOR_RED,COLOR_YELLOW);
|
||||
init_pair(6,COLOR_RED,COLOR_MAGENTA);
|
||||
for(byte b= 0;b<6;b++){
|
||||
colors[b]=COLOR_PAIR(b+1);
|
||||
}
|
||||
|
||||
}
|
||||
py=px=0;
|
||||
untouched=len*wid;
|
||||
int flags=0;
|
||||
byte board[len][wid];
|
||||
bool mines[len][wid];
|
||||
char result[70];
|
||||
int input;
|
||||
|
||||
memset(board,-1,len*wid);
|
||||
memset(mines,false,len*wid);
|
||||
mine(mines);
|
||||
|
||||
while(1){
|
||||
erase();
|
||||
mvprintw(1,0,"|\\/| Flags:%d\n",flags);
|
||||
mvprintw(2,0,"| |INES Mines:%d\n",mscount);
|
||||
draw(3,0,board);
|
||||
refresh();
|
||||
if(untouched<=mscount){
|
||||
strcpy(result,"You won!");
|
||||
break;
|
||||
}
|
||||
input = getch();
|
||||
if( (input=='k' || input==KEY_UP) && py>0)
|
||||
py--;
|
||||
if( (input=='j' || input==KEY_DOWN) && py<len-1)
|
||||
py++;
|
||||
if( (input=='h' || input==KEY_LEFT) && px>0)
|
||||
px--;
|
||||
if( (input=='l' || input==KEY_RIGHT) && px<wid-1)
|
||||
px++;
|
||||
if( input=='q')
|
||||
sigint_handler(0);
|
||||
if(input=='x' && getch()=='y' && getch()=='z' && getch()=='z' && getch()=='y' ){
|
||||
strcpy(result,"It is now pitch dark. If you proceed you will likely fall into a pit.");
|
||||
break;
|
||||
}
|
||||
if(input=='\n' && board[py][px] < 9){
|
||||
if(mines[py][px]){
|
||||
strcpy(result,"You lost The Game.");
|
||||
break;
|
||||
}
|
||||
click(board,mines,py,px);
|
||||
}
|
||||
if(input==' '){
|
||||
if(board[py][px] == -1){
|
||||
board[py][px]=9;//flag
|
||||
flags++;
|
||||
}
|
||||
else if(board[py][px] == 9){
|
||||
board[py][px]=10;//unclear
|
||||
flags--;
|
||||
}
|
||||
else if(board[py][px] == 10)
|
||||
board[py][px]=-1;
|
||||
}
|
||||
}
|
||||
drawmines(3,0,board,mines);
|
||||
mvprintw(len+5,0,"%s Wanna play again?(y/n)",result);
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
if(input == 'Y' || input == 'y')
|
||||
goto Start;
|
||||
endwin();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
340
games/reversi.c
340
games/reversi.c
@ -1,340 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
/*
|
||||
_
|
||||
|_)
|
||||
| \EVERSI
|
||||
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
compile with -lncurses
|
||||
*/
|
||||
typedef signed char byte;
|
||||
byte py,px;//cursor
|
||||
const char piece[2] = "OX";
|
||||
char game[8][8];//main board
|
||||
byte computer[2] = {0,0};
|
||||
byte score[2];//set by header()
|
||||
|
||||
void rectangle(byte sy,byte sx){
|
||||
for(byte y=0;y<=8+1;y++){
|
||||
mvaddch(sy+y,sx,ACS_VLINE);
|
||||
mvaddch(sy+y,sx+8*2,ACS_VLINE);
|
||||
}
|
||||
for(byte x=0;x<=8*2;x++){
|
||||
mvaddch(sy,sx+x,ACS_HLINE);
|
||||
mvaddch(sy+8+1,sx+x,ACS_HLINE);
|
||||
}
|
||||
mvaddch(sy,sx,ACS_ULCORNER);
|
||||
mvaddch(sy+8+1,sx,ACS_LLCORNER);
|
||||
mvaddch(sy,sx+8*2,ACS_URCORNER);
|
||||
mvaddch(sy+8+1,sx+8*2,ACS_LRCORNER);
|
||||
}
|
||||
|
||||
void header(void){//buse
|
||||
score[0]=score[1]=0;
|
||||
for(byte y=0;y<8;y++){
|
||||
for(byte x=0;x<8;x++){
|
||||
if(game[y][x]){
|
||||
if(game[y][x]==piece[0])
|
||||
score[0]++;
|
||||
else
|
||||
score[1]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mvaddch(0,1, '_');
|
||||
mvprintw(1,0,"|_) %2d:%2d",score[0],score[1]);
|
||||
mvprintw(2,0,"| \\EVERSI ");
|
||||
}
|
||||
|
||||
void draw(byte sy,byte sx){//the game's board
|
||||
rectangle(sy,sx);
|
||||
chtype attr ;
|
||||
for(byte y=0;y<8;y++){
|
||||
for(byte x=0;x<8;x++){
|
||||
attr=A_NORMAL;
|
||||
if(y==py && x==px)
|
||||
attr |= A_STANDOUT;
|
||||
if(game[y][x])
|
||||
mvaddch(sy+1+y,sx+x*2+1,attr|game[y][x]);
|
||||
else
|
||||
mvaddch(sy+1+y,sx+x*2+1,attr|'.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool can_reverse(byte ty , byte tx,char board[8][8],char piece){//can do a move there?
|
||||
byte y,x,count;
|
||||
if(board[ty][tx])
|
||||
return false;
|
||||
for(byte dy=-1;dy<2;dy++){ //changes the direction
|
||||
for(byte dx=-1;dx<2;dx++){
|
||||
if(dx==0&&dy==0)//infinite
|
||||
dx=1;
|
||||
count=0;
|
||||
y=ty+dy;
|
||||
x=tx+dx;
|
||||
while(1){
|
||||
if(y<0 || y>=8 ||x<0 || x>=8){//reaches edges of the board
|
||||
count=0;
|
||||
break;
|
||||
}
|
||||
if(!board[y][x]){//gap
|
||||
count=0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(board[y][x]!=piece){
|
||||
count++;
|
||||
y+=dy;
|
||||
x+=dx;
|
||||
}
|
||||
else
|
||||
break;//same color
|
||||
}
|
||||
if(count)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void reverse(byte ty,byte tx,char board[8][8],char piece){
|
||||
board[ty][tx]=piece;
|
||||
byte y,x;
|
||||
for(byte dy=-1;dy<2;dy++){//changes the direction
|
||||
for(byte dx=-1;dx<2;dx++){
|
||||
if(dy==0 && dx==0)
|
||||
dx=1;
|
||||
y=ty+dy;
|
||||
x=tx+dx;
|
||||
while(1){
|
||||
if(y<0 || y>=8 || x<0 || x>=8)
|
||||
break;
|
||||
if(!board[y][x])
|
||||
break;
|
||||
if(board[y][x]!=piece){
|
||||
y+=dy;
|
||||
x+=dx;
|
||||
}
|
||||
else{ //of same kind
|
||||
while(y!=ty || x!=tx){ //reverse the disks
|
||||
board[y][x]=piece;
|
||||
y-=dy;
|
||||
x-=dx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool can_move(char board[8][8],char piece){//can move at all?
|
||||
for(byte y=0;y<8;y++)
|
||||
for(byte x=0;x<8;x++)
|
||||
if(can_reverse(y,x,board,piece))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
double advantage(char board[8][8],char piece){
|
||||
double own=0;
|
||||
double opp=0;
|
||||
for(byte y=0;y<8;y++){
|
||||
for(byte x=0;x<8;x++){
|
||||
if(board[y][x]){
|
||||
if(board[y][x]==piece){
|
||||
own++;
|
||||
if( ((y==7 || y==0)&&(x!=7 && x!=0)) || ((x==7 || x==0)&&(y!=7 && y!=0)) )//edges
|
||||
own+=100;
|
||||
if( (y==7 || y==0)&&(x==7 || x==0) )//corners
|
||||
own+=10000;
|
||||
}
|
||||
else{
|
||||
opp++;
|
||||
if( ((y==7 || y==0)&&(x!=7 && x!=0)) || ((x==7 || x==0)&&(y!=7 && y!=0)) )
|
||||
opp+=100;
|
||||
if( (y==7 || y==0)&&(x==7 || x==0) )
|
||||
opp+=10000;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return own/opp;
|
||||
}
|
||||
|
||||
void cp(char A[8][8],char B[8][8]){
|
||||
for(byte y=0;y<8;y++)
|
||||
for(byte x=0;x<8;x++)
|
||||
B[y][x]=A[y][x];
|
||||
}
|
||||
|
||||
double decide(char board[8][8],char piece,char opponet,byte depth){//AI algorithm
|
||||
if(!can_move(board,piece))
|
||||
return 0;
|
||||
char plan[8][8];
|
||||
double adv,bestadv;
|
||||
adv=bestadv=0;
|
||||
byte besty,bestx;
|
||||
for(byte y=0;y<8;y++){
|
||||
for(byte x=0;x<8;x++){
|
||||
if(can_reverse(y,x,board,piece) ){
|
||||
cp(board,plan);//backtrack
|
||||
reverse(y,x,plan,piece);
|
||||
if(depth){
|
||||
adv= decide(plan,opponet,piece,depth-1);//least benefit for the opponet
|
||||
if(adv) //the opponet can make a move
|
||||
adv = 1/adv;
|
||||
else
|
||||
adv=advantage(plan,piece);
|
||||
}
|
||||
else
|
||||
adv=advantage(plan,piece);
|
||||
if(adv>bestadv){
|
||||
bestadv=adv;
|
||||
besty=y;
|
||||
bestx=x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reverse(besty,bestx,board,piece);//do the move
|
||||
return bestadv;
|
||||
}
|
||||
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
|
||||
int main(int argc , char** argv){
|
||||
int depth=3;
|
||||
if(argc>2){
|
||||
printf("Usage:%s [AIpower]",argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(argc==2){
|
||||
if(sscanf(argv[1],"%d",&depth) && depth<128 && 0<depth)
|
||||
;//already done
|
||||
else{
|
||||
printf("That should be a number from 1 to 127.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
signal(SIGINT,sigint_handler);
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr,1);
|
||||
int input;
|
||||
printw("Black plays first:\n");
|
||||
printw("Choose type of the white player (H/c)\n");
|
||||
input=getch();
|
||||
if(input == 'c'){
|
||||
computer[0]=depth;
|
||||
printw("Computer.\n");
|
||||
}
|
||||
else{
|
||||
computer[1]=0;
|
||||
printw("Human.\n");
|
||||
}
|
||||
printw("Choose type of the black player(h/C)\n");
|
||||
input=getch();
|
||||
if(input == 'h'){
|
||||
computer[1]=0;
|
||||
printw("Human.\n");
|
||||
}
|
||||
else{
|
||||
computer[1]=depth;
|
||||
printw("Computer.\n");
|
||||
}
|
||||
Start:
|
||||
curs_set(0);
|
||||
py=px=0;
|
||||
memset(game,0,64);
|
||||
bool turn=0;
|
||||
byte cantmove=0;
|
||||
game[3][3]=piece[0];
|
||||
game[4][4]=piece[0];
|
||||
game[3][4]=piece[1];
|
||||
game[4][3]=piece[1];
|
||||
|
||||
Turn:
|
||||
erase();
|
||||
flushinp();
|
||||
header();
|
||||
draw(3,0);
|
||||
refresh();
|
||||
if(cantmove >=2)
|
||||
goto End;
|
||||
|
||||
turn = !turn;
|
||||
if(computer[turn]){
|
||||
if(can_move(game,piece[turn])){
|
||||
mvprintw(13,0,"Thinking...");
|
||||
refresh();
|
||||
decide(game,piece[turn],piece[!turn],computer[turn]);
|
||||
cantmove=0;
|
||||
}
|
||||
else
|
||||
cantmove++;
|
||||
goto Turn;
|
||||
|
||||
}
|
||||
|
||||
if(!can_move(game,piece[turn])){
|
||||
cantmove++;
|
||||
goto Turn;
|
||||
}
|
||||
else{
|
||||
cantmove=0;
|
||||
while(1){ //human control
|
||||
erase();
|
||||
header();
|
||||
draw(3,0);
|
||||
input=getch();
|
||||
if( (input=='k' || input==KEY_UP) && py>0)
|
||||
py--;
|
||||
if( (input=='j' || input==KEY_DOWN) && py<7)
|
||||
py++;
|
||||
if( (input=='h' || input==KEY_LEFT) && px>0)
|
||||
px--;
|
||||
if( (input=='l' || input==KEY_RIGHT) && px<7)
|
||||
px++;
|
||||
if( input=='q')
|
||||
sigint_handler(0);
|
||||
if(input=='\n'){
|
||||
if(can_reverse(py,px,game,piece[turn])){
|
||||
reverse(py,px,game,piece[turn]);
|
||||
goto Turn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
End:
|
||||
if(score[0]==score[1])
|
||||
mvprintw(13,0,"Draw!!");
|
||||
else if(score[0] > score[1])
|
||||
mvprintw(13,0,"'%c' won.",piece[0]);
|
||||
else
|
||||
mvprintw(13,0,"'%c' won.",piece[1]);
|
||||
|
||||
printw(" Wanna play again?(y/N)");
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
|
||||
if(input == 'Y' || input == 'y')
|
||||
goto Start;
|
||||
endwin();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
287
games/sudoku.c
287
games/sudoku.c
@ -1,287 +0,0 @@
|
||||
#include <curses.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h> //to seed random
|
||||
#include <limits.h>
|
||||
#include <signal.h>
|
||||
/*
|
||||
_
|
||||
(_
|
||||
_)UDOKU
|
||||
|
||||
|
||||
copyright Hossein Bakhtiarifar 2018 (c)
|
||||
No rights are reserved and this software comes with no warranties of any kind to the extent permitted by law.
|
||||
|
||||
compile with -lncurses
|
||||
*/
|
||||
typedef unsigned char byte;
|
||||
byte size,s,ds;//s=size*size
|
||||
byte py,px;
|
||||
byte diff;
|
||||
unsigned int filled;
|
||||
chtype colors[6]={0};
|
||||
void cross(byte sy,byte sx,chtype start,chtype middle,chtype end){ //to simplify drawing tables
|
||||
mvaddch(sy,sx,start);
|
||||
byte f = 2*size;
|
||||
for(char n=1;n<size;n++){
|
||||
mvaddch(sy,sx+f,middle);
|
||||
f+=2*size;
|
||||
}
|
||||
mvaddch(sy,sx+f,end);
|
||||
}
|
||||
|
||||
void table(byte sy,byte sx){ //empty table
|
||||
byte l;//line
|
||||
for(l=0;l<=size;l++){
|
||||
for(byte y=0;y<=ds;y++)
|
||||
mvaddch(sy+y,sx+l*size*2,ACS_VLINE);
|
||||
for(byte x=0;x<=s*2;x++)
|
||||
mvaddch(sy+(size+1)*l,sx+x,ACS_HLINE);
|
||||
}
|
||||
cross(sy,sx,ACS_ULCORNER,ACS_TTEE,ACS_URCORNER);
|
||||
for(l=1;l<size;l++)
|
||||
cross(sy+l*size+l,sx,ACS_LTEE,ACS_PLUS,ACS_RTEE);
|
||||
cross(sy+l*size+l,sx,ACS_LLCORNER,ACS_BTEE,ACS_LRCORNER);
|
||||
}
|
||||
|
||||
byte sgn2int(char sgn){
|
||||
if('0'<sgn && sgn <='9')
|
||||
return sgn-'0';
|
||||
if('a'<=sgn && sgn <='z')
|
||||
return sgn-'a'+10;
|
||||
if('A'<=sgn && sgn <= 'Z')
|
||||
return sgn-'A'+36;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char int2sgn(byte num){//integer to representing sign
|
||||
if(0< num && num <= 9)
|
||||
return num+'0';
|
||||
else if(10<=num && num <=35)
|
||||
return num-10+'a';
|
||||
else if(36<=num && num <=51)
|
||||
return num-36+'A';
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool isvalid(byte ty,byte tx,char board[s][s]){ //is it legal to place that char there?
|
||||
char t= board[ty][tx];
|
||||
if(!t)
|
||||
return 0;
|
||||
byte y,x;
|
||||
for(y=0;y<s;y++){
|
||||
if(board[y][tx] == t && y!=ty)
|
||||
return 0;
|
||||
}
|
||||
for(x=0;x<s;x++){
|
||||
if(board[ty][x] == t && x!= tx)
|
||||
return 0;
|
||||
}
|
||||
byte sy=size*(ty/size);//square
|
||||
byte sx=size*(tx/size);
|
||||
for(y=0;y<size;y++){
|
||||
for(x=0;x<size;x++){
|
||||
if(board[sy+y][sx+x]==t && sy+y != ty && sx+x != tx)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void genocide(char board[s][s],char victim){
|
||||
for(byte y=0;y<s;y++)
|
||||
for(byte x=0;x<s;x++)
|
||||
if(board[y][x]==victim)
|
||||
board[y][x]=0;
|
||||
}
|
||||
bool fill_with(char board[s][s],char fillwith){//returns 1 on failure
|
||||
byte firstx,x,tries=0;
|
||||
Again:
|
||||
tries++;
|
||||
if (tries>s)
|
||||
return 1;
|
||||
for(byte y=0;y<s;y++){
|
||||
firstx=x=random()%s;
|
||||
while(1){
|
||||
if(!board[y][x]){
|
||||
board[y][x]=fillwith;
|
||||
if(isvalid(y,x,board)){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
board[y][x]=0;
|
||||
goto Next;
|
||||
}
|
||||
}
|
||||
else{
|
||||
Next:
|
||||
x++;
|
||||
if(x==s)
|
||||
x=0;
|
||||
if(x==firstx){
|
||||
genocide(board,fillwith);
|
||||
goto Again;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
return 0;
|
||||
}
|
||||
void fill(char board[s][s]){
|
||||
for(byte num=1;num<=s;num++){
|
||||
if ( fill_with(board,int2sgn(num) ) ){
|
||||
memset(board,0,s*s);
|
||||
num=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
void mkpuzzle(char board[s][s],char empty[s][s],char game[s][s]){//makes a puzzle to solve
|
||||
for(byte y=0;y<s;y++){
|
||||
for(byte x=0;x<s;x++){
|
||||
if( !(random()%diff) ){
|
||||
empty[y][x]=board[y][x];
|
||||
game[y][x]=board[y][x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void header(byte sy,byte sx){
|
||||
mvaddch(sy, sx+1, '_');
|
||||
mvprintw(sy+1,sx,"(_ Solved:%d/%d",filled,s*s);
|
||||
mvprintw(sy+2,sx," _)UDOKU Left :%d/%d",s*s-filled,s*s);
|
||||
}
|
||||
|
||||
void draw(byte sy,byte sx,char empty[s][s],char board[s][s]){
|
||||
chtype attr;
|
||||
table(sy,sx);
|
||||
filled=0;
|
||||
for(byte y=0;y<s;y++){
|
||||
for(byte x=0;x<s;x++){
|
||||
attr=A_NORMAL;
|
||||
if(x==px && y==py)
|
||||
attr |= A_STANDOUT;
|
||||
if(empty[y][x])
|
||||
attr |= A_BOLD;
|
||||
if(board[y][x]){
|
||||
if(!isvalid(y,x,board))
|
||||
attr |= colors[5];
|
||||
else{
|
||||
attr |= colors[board[y][x]%5];
|
||||
filled++;
|
||||
}
|
||||
mvaddch(sy+y+y/size+1,sx+x*2+1,attr|board[y][x]);
|
||||
}
|
||||
else
|
||||
mvaddch(sy+y+y/size+1,sx+x*2+1,attr|' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sigint_handler(int x){
|
||||
endwin();
|
||||
puts("Quit.");
|
||||
exit(x);
|
||||
}
|
||||
|
||||
int main(int argc,char** argv){
|
||||
signal(SIGINT,sigint_handler);
|
||||
if(argc>3 || (argc==2 && !strcmp("help",argv[1])) ){
|
||||
printf("Usage: %s [size [ diff]]\n",argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if(argc>1 ){
|
||||
if(strlen(argv[1])>1 || argv[1][0]-'0'>7 || argv[1][0]-'0'< 2){
|
||||
printf("2 <= size <= 7\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
size = *argv[1]-'0';
|
||||
}
|
||||
else
|
||||
size=3;
|
||||
if(argc>2){
|
||||
if (strlen(argv[2])>1 || argv[2][0]-'0'>4 || argv[2][0]-'0'<= 0 ){
|
||||
printf("1 <= diff <=4\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
diff = *argv[2]-'0'+1;
|
||||
}
|
||||
else
|
||||
diff=2;
|
||||
|
||||
|
||||
|
||||
Start:
|
||||
initscr();
|
||||
noecho();
|
||||
cbreak();
|
||||
keypad(stdscr,1);
|
||||
curs_set(0);
|
||||
srandom(time(NULL)%UINT_MAX);
|
||||
if( has_colors() ){
|
||||
start_color();
|
||||
use_default_colors();
|
||||
init_pair(1,COLOR_YELLOW,-1);
|
||||
init_pair(2,COLOR_GREEN,-1);
|
||||
init_pair(3,COLOR_BLUE,-1);
|
||||
init_pair(4,COLOR_CYAN,-1);
|
||||
init_pair(5,COLOR_MAGENTA,-1);
|
||||
init_pair(6,COLOR_RED,-1);
|
||||
for(byte b=0;b<6;b++){
|
||||
colors[b]=COLOR_PAIR(b+1);
|
||||
}
|
||||
}
|
||||
filled =0;
|
||||
s=size*size;
|
||||
ds=s+size;
|
||||
char board[s][s];
|
||||
char empty[s][s];
|
||||
char game[s][s];
|
||||
memset(board,0,s*s);
|
||||
memset(empty,0,s*s);
|
||||
memset(game,0,s*s);
|
||||
int input=0 ;
|
||||
fill(board);
|
||||
mkpuzzle(board,empty,game);
|
||||
py=px=0;
|
||||
|
||||
while(1){
|
||||
erase();
|
||||
draw(3,0,empty,game);
|
||||
header(0,0);
|
||||
refresh();
|
||||
if(filled == s*s)
|
||||
break;
|
||||
input = getch();
|
||||
if(input == KEY_UP && py)
|
||||
py--;
|
||||
if(input == KEY_DOWN && py<s-1)
|
||||
py++;
|
||||
if(input == KEY_LEFT && px)
|
||||
px--;
|
||||
if(input == KEY_RIGHT && px<s-1)
|
||||
px++;
|
||||
if(!empty[py][px]){
|
||||
if(input == ' ' )
|
||||
game[py][px]=0;
|
||||
else if(input<=CHAR_MAX && sgn2int(input) && sgn2int(input)<=s )
|
||||
game[py][px]=input;
|
||||
}
|
||||
if(input == 'q' && size<5)
|
||||
sigint_handler(EXIT_SUCCESS);
|
||||
if(input == 'x' && getch()=='y' && getch()=='z' && getch()=='z' && getch()=='y')
|
||||
game[py][px]=board[py][px];
|
||||
}
|
||||
mvprintw(ds+4,0,"YAY!! Wanna play again?(y/n)");
|
||||
curs_set(1);
|
||||
input=getch();
|
||||
if(input == 'Y' || input == 'y')
|
||||
goto Start;
|
||||
endwin();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user