splitted out parts of server.c to game.c and asciiart.c, rewritten the asciiart part a bit. things still seem to work
This commit is contained in:
parent
c606818adc
commit
02eb1c6cde
@ -1,3 +1,3 @@
|
|||||||
CFLAGS=-g -std=gnu99 -Wall -pedantic
|
CFLAGS=-g -std=gnu99 -Wall -pedantic
|
||||||
|
|
||||||
server: server.o net.o
|
server: server.o net.o asciiart.o game.o
|
||||||
|
111
src/asciiart.c
Normal file
111
src/asciiart.c
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/* -*- c-basic-offset: 4 -*- */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "asciiart.h"
|
||||||
|
|
||||||
|
#define SMALL_WIDTH ASCIIART_SMALL_BOARD_WIDTH
|
||||||
|
#define SMALL_HEIGHT ASCIIART_SMALL_BOARD_HEIGHT
|
||||||
|
|
||||||
|
char asciiart_small_blank_board[] =
|
||||||
|
"red \n"
|
||||||
|
" | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" A| | | | | | | | | | |A \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" B| | | | | | | | | | |B \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" C| | | | | | | | | | |C \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" D| | | | | | | | | | |D \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" E| | | | | | | | | | |E \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" F| | | | | | | | | | |F \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" G| | | | | | | | | | |G \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" H| | | | | | | | | | |H \n"
|
||||||
|
"--+--+--+--+--+--+--+--+--+--+--+--\n"
|
||||||
|
" | 0| 1| 2| 3| 4| 5| 6| 7| 8| 9| \n"
|
||||||
|
" silver\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
char asciiart_small_pieces[] =
|
||||||
|
" " // NONE
|
||||||
|
"SSSSSSSSRRRRRRRR"
|
||||||
|
",'`.,'`..\"\"..\"\"." // DJHED
|
||||||
|
"`/\\'/.,\\\"/\\\"/==\\" // PYRAMID
|
||||||
|
". . . . = = = = " // OBELISK
|
||||||
|
"........========" // OBELISK2
|
||||||
|
;
|
||||||
|
|
||||||
|
int
|
||||||
|
asciiart_small_square_index(int x, int y)
|
||||||
|
{
|
||||||
|
return SMALL_WIDTH*(y*2+3)+(x*3+3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
asciiart_small_draw_piece(char *buf, int x, int y, square_t square)
|
||||||
|
{
|
||||||
|
int piece_index = (square.piece*4*2 + square.side*4 + square.dir) * 2;
|
||||||
|
int buf_index = asciiart_small_square_index(x, y);
|
||||||
|
buf[buf_index] = asciiart_small_pieces[piece_index];
|
||||||
|
buf[buf_index+1] = asciiart_small_pieces[piece_index+1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
asciiart_small_draw_grid(char *buf)
|
||||||
|
{
|
||||||
|
strcpy(buf, asciiart_small_blank_board);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
asciiart_small_draw_laserhit(char *buf, game_t *game)
|
||||||
|
{
|
||||||
|
int x, y, i;
|
||||||
|
|
||||||
|
x = game->laser_pos[0];
|
||||||
|
y = game->laser_pos[1];
|
||||||
|
|
||||||
|
if (x == -1 && y == -1) return;
|
||||||
|
|
||||||
|
i = asciiart_small_square_index(x, y);
|
||||||
|
if (x == -1 || x == BOARD_WIDTH) {
|
||||||
|
buf[i] = '#';
|
||||||
|
} else {
|
||||||
|
if (y == -1)
|
||||||
|
i += SMALL_WIDTH;
|
||||||
|
else if (y == BOARD_HEIGHT)
|
||||||
|
i -= SMALL_WIDTH;
|
||||||
|
buf[i] = buf[i+1] = '#';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
asciiart_small_draw_board(char *buf, game_t *game)
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
asciiart_small_draw_grid(buf);
|
||||||
|
for (y = 0; y < BOARD_HEIGHT; y++) {
|
||||||
|
for (x = 0; x < BOARD_WIDTH; x++) {
|
||||||
|
asciiart_small_draw_piece(buf, x, y, game->board[x][y]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
asciiart_small_draw_laserhit(buf, game);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
printf("%d, %d\n", strlen(asciiart_small_blank_board), SMALL_WIDTH*SMALL_HEIGHT);
|
||||||
|
char buf[SMALL_WIDTH*SMALL_HEIGHT+1];
|
||||||
|
asciiart_small_draw_board(buf);
|
||||||
|
printf("+++\n%s+++\n", buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
10
src/asciiart.h
Normal file
10
src/asciiart.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef KHET_ASCIIART_H
|
||||||
|
#define KHET_ASCIIART_H
|
||||||
|
|
||||||
|
#define ASCIIART_SMALL_BOARD_WIDTH 36
|
||||||
|
#define ASCIIART_SMALL_BOARD_HEIGHT 21
|
||||||
|
#define ASCIIART_SMALL_BUFSZ ((ASCIIART_SMALL_BOARD_WIDTH)*(ASCIIART_SMALL_BOARD_HEIGHT)+1)
|
||||||
|
|
||||||
|
void asciiart_small_draw_board(char *buf, game_t *game);
|
||||||
|
|
||||||
|
#endif
|
255
src/game.c
Normal file
255
src/game.c
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
/* -*- c-basic-offset: 4 -*- */
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
struct pieceinfo {
|
||||||
|
int num;
|
||||||
|
} pieceinfo[] = {
|
||||||
|
{ // NONE
|
||||||
|
.num = 0 },
|
||||||
|
{ // PHARAO
|
||||||
|
.num = 1 },
|
||||||
|
{ // DJHED
|
||||||
|
.num = 2 },
|
||||||
|
{ // PYRAMID
|
||||||
|
.num = 7 },
|
||||||
|
{ // OBELISK
|
||||||
|
.num = 4 },
|
||||||
|
{ // OBELISK2
|
||||||
|
.num = 0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
sideinfo_t sideinfo[] = {
|
||||||
|
{ .ch = '.', .name = "silver" },
|
||||||
|
{ .ch = '=', .name = "red" }
|
||||||
|
};
|
||||||
|
|
||||||
|
char classic_setup[] =
|
||||||
|
"H40" // PHARAO
|
||||||
|
"E40E51" // DJHED
|
||||||
|
"H22G73E22D21E91D92C32" // PYRAMID
|
||||||
|
"H30H30H50H50" // OBELISK
|
||||||
|
;
|
||||||
|
|
||||||
|
int
|
||||||
|
laser_at(game_t *game, int x, int y)
|
||||||
|
{
|
||||||
|
return game->laser_pos[0] == x && game->laser_pos[1] == y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
laser(game_t *game, int side) {
|
||||||
|
#define lreturn(v) do { retval=(v); goto ret; } while (0);
|
||||||
|
int x, y, dir;
|
||||||
|
int ddir;
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/*
|
||||||
|
dir:
|
||||||
|
0
|
||||||
|
3 X 1
|
||||||
|
2
|
||||||
|
*/
|
||||||
|
|
||||||
|
net_all_printf("LASER (%s)\n", sideinfo[side].name);
|
||||||
|
|
||||||
|
assert(side == 0 || side == 1);
|
||||||
|
switch (side) {
|
||||||
|
case 0:
|
||||||
|
x=9; y=7; dir=0;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
x=0; y=0; dir=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
net_all_printf("pos: (%d,%d)\n", y, x);
|
||||||
|
switch (game->board[x][y].piece) {
|
||||||
|
case NONE:
|
||||||
|
break;
|
||||||
|
case PHARAO:
|
||||||
|
lreturn(SILVER_WINS + 1-game->board[x][y].side); /* GAME OVER */
|
||||||
|
case OBELISK2:
|
||||||
|
game->board[x][y].piece = OBELISK;
|
||||||
|
lreturn(L_PIECE);
|
||||||
|
case OBELISK:
|
||||||
|
game->board[x][y].piece = NONE;
|
||||||
|
lreturn(L_PIECE);
|
||||||
|
case DJHED:
|
||||||
|
ddir = (game->board[x][y].dir - dir) & 3;
|
||||||
|
dir=(dir + 1 - 2*(ddir & 1)) & 3;
|
||||||
|
break;
|
||||||
|
case PYRAMID:
|
||||||
|
ddir = (game->board[x][y].dir - dir) & 3;
|
||||||
|
if (ddir & 2) {
|
||||||
|
game->board[x][y].piece = NONE;
|
||||||
|
lreturn(L_PIECE);
|
||||||
|
}
|
||||||
|
dir=(dir + 1 - 2*(ddir & 1)) & 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (dir & 3) {
|
||||||
|
case 0: y--;
|
||||||
|
if (y<0) lreturn(L_WALL);
|
||||||
|
break;
|
||||||
|
case 1: x++;
|
||||||
|
if (x>BOARD_WIDTH-1) lreturn(L_WALL);
|
||||||
|
break;
|
||||||
|
case 2: y++;
|
||||||
|
if (y>BOARD_HEIGHT-1) lreturn(L_WALL);
|
||||||
|
break;
|
||||||
|
case 3: x--;
|
||||||
|
if (x<0) lreturn(L_WALL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret:
|
||||||
|
game->laser_pos[0] = x;
|
||||||
|
game->laser_pos[1] = y;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
movable(game_t *game, int row, int col, int side)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
row>=0 && row<BOARD_HEIGHT &&
|
||||||
|
col>=0 && col<BOARD_WIDTH &&
|
||||||
|
game->board[col][row].piece != NONE &&
|
||||||
|
game->board[col][row].side == side;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
rotate(game_t *game, int side, int row, int col, rot_t dir)
|
||||||
|
{
|
||||||
|
int incr;
|
||||||
|
|
||||||
|
if (!movable(game, row, col, side))
|
||||||
|
return E_ILLEGAL_MOVE;
|
||||||
|
|
||||||
|
assert(dir==R_CW || dir==R_CCW);
|
||||||
|
|
||||||
|
incr = dir==R_CW ? 1 : -1;
|
||||||
|
game->board[col][row].dir = (game->board[col][row].dir + incr) & 3;
|
||||||
|
return HUGE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
move(game_t *game, int side, int row, int col, int dir, int flags) {
|
||||||
|
if (!movable(game, row, col, side))
|
||||||
|
return E_ILLEGAL_MOVE;
|
||||||
|
|
||||||
|
/* dir =
|
||||||
|
0 1 2
|
||||||
|
7 X 3
|
||||||
|
6 5 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
assert((dir>=0) || (dir<=7));
|
||||||
|
int nrow = row - (dir<3) + ((dir>3) && (dir<7));
|
||||||
|
int ncol = col + ((dir>1) && (dir<5)) - ((dir<1) || (dir>5));
|
||||||
|
if ((ncol<0) || (ncol>9) || (nrow<0) || (nrow>7))
|
||||||
|
return E_ILLEGAL_MOVE;
|
||||||
|
|
||||||
|
if (flags & F_SPLIT) {
|
||||||
|
if (game->board[ncol][nrow].piece || (game->board[col][row].piece != OBELISK2))
|
||||||
|
return E_ILLEGAL_MOVE;
|
||||||
|
game->board[col][row].piece = OBELISK;
|
||||||
|
game->board[ncol][nrow].piece = OBELISK;
|
||||||
|
game->board[ncol][nrow].side = game->board[col][row].side;
|
||||||
|
return HUGE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game->board[ncol][nrow].piece &&
|
||||||
|
!((game->board[col][row].piece == DJHED) &&
|
||||||
|
((game->board[ncol][nrow].piece != DJHED) &&
|
||||||
|
(game->board[ncol][nrow].piece != PHARAO))))
|
||||||
|
return E_ILLEGAL_MOVE;
|
||||||
|
|
||||||
|
struct square tmp;
|
||||||
|
tmp = game->board[ncol][nrow];
|
||||||
|
game->board[ncol][nrow] = game->board[col][row];
|
||||||
|
game->board[col][row] = tmp;
|
||||||
|
|
||||||
|
return HUGE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
place(game_t *game, int row, int col, int piece, int side, int dir)
|
||||||
|
{
|
||||||
|
if (game->board[col][row].piece == OBELISK &&
|
||||||
|
game->board[col][row].side == side &&
|
||||||
|
piece == OBELISK) {
|
||||||
|
piece = OBELISK2;
|
||||||
|
} else if (game->board[col][row].piece != NONE &&
|
||||||
|
piece != NONE) {
|
||||||
|
fprintf(stderr, "error: trying to place a piece on a non-empty square\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
game->board[col][row].piece = piece;
|
||||||
|
game->board[col][row].side = side;
|
||||||
|
game->board[col][row].dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clear_board(game_t *game)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
for (i = 0; i < BOARD_HEIGHT; i++)
|
||||||
|
for (j = 0; j < BOARD_WIDTH; j++)
|
||||||
|
place(game, i, j, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_board_place_piece(game_t *game, int piece, int side, char *place_desc)
|
||||||
|
{
|
||||||
|
int row, col, dir;
|
||||||
|
|
||||||
|
row = place_desc[0]-'A';
|
||||||
|
col = place_desc[1]-'0';
|
||||||
|
dir = place_desc[2]-'0';
|
||||||
|
|
||||||
|
if (side == 1) {
|
||||||
|
row = BOARD_HEIGHT-row-1;
|
||||||
|
col = BOARD_WIDTH-col-1;
|
||||||
|
dir = (dir+2)&3;
|
||||||
|
}
|
||||||
|
|
||||||
|
place(game, row, col, piece, side, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_board(game_t *game, char *desc)
|
||||||
|
{
|
||||||
|
int side, piece, num, i;
|
||||||
|
|
||||||
|
clear_board(game);
|
||||||
|
|
||||||
|
for (side = 0; side < 2; side++) {
|
||||||
|
i = 0;
|
||||||
|
for (piece = 0; piece < N_PIECE_TYPES; piece++) {
|
||||||
|
for (num = 0; num < pieceinfo[piece].num; num++) {
|
||||||
|
setup_board_place_piece(game, piece, side,
|
||||||
|
&desc[i*3]);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
init_game(game_t *game)
|
||||||
|
{
|
||||||
|
game->move = 0;
|
||||||
|
game->winner = -1;
|
||||||
|
game->laser_pos[0] = game->laser_pos[1] = -1;
|
||||||
|
clear_board(game);
|
||||||
|
}
|
||||||
|
|
66
src/game.h
Normal file
66
src/game.h
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#ifndef KHET_GAME_H
|
||||||
|
#define KHET_GAME_H
|
||||||
|
|
||||||
|
#define NONE 0
|
||||||
|
#define PHARAO 1
|
||||||
|
#define DJHED 2
|
||||||
|
#define PYRAMID 3
|
||||||
|
#define OBELISK 4
|
||||||
|
#define OBELISK2 5
|
||||||
|
|
||||||
|
#define N_PIECE_TYPES 6
|
||||||
|
|
||||||
|
#define SILVER 0
|
||||||
|
#define RED 1
|
||||||
|
|
||||||
|
#define BOARD_WIDTH 10
|
||||||
|
#define BOARD_HEIGHT 8
|
||||||
|
|
||||||
|
#define F_ROTATE 1
|
||||||
|
#define F_SPLIT 2
|
||||||
|
|
||||||
|
#define E_ILLEGAL_MOVE -1
|
||||||
|
#define E_UNKNOWN_COMMAND -2
|
||||||
|
#define HUGE_SUCCESS 1
|
||||||
|
|
||||||
|
// return values for laser():
|
||||||
|
#define L_WALL 0
|
||||||
|
#define L_PIECE 1
|
||||||
|
#define SILVER_WINS 2
|
||||||
|
#define RED_WINS 3
|
||||||
|
|
||||||
|
typedef struct square {
|
||||||
|
unsigned int piece : 4;
|
||||||
|
unsigned int side : 1;
|
||||||
|
unsigned int dir : 2;
|
||||||
|
} square_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int move;
|
||||||
|
int winner;
|
||||||
|
square_t board[BOARD_WIDTH][BOARD_HEIGHT];
|
||||||
|
int laser_pos[2];
|
||||||
|
} game_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char ch;
|
||||||
|
char *name;
|
||||||
|
} sideinfo_t;
|
||||||
|
|
||||||
|
typedef enum { R_CW, R_CCW } rot_t;
|
||||||
|
typedef enum { D_NW=0, D_N, D_NE, D_E, D_SE, D_S, D_SW, D_W } dir_t;
|
||||||
|
|
||||||
|
extern char classic_setup[];
|
||||||
|
extern sideinfo_t sideinfo[];
|
||||||
|
|
||||||
|
int laser_at(game_t *game, int x, int y);
|
||||||
|
int laser(game_t *game, int side);
|
||||||
|
int movable(game_t *game, int row, int col, int side);
|
||||||
|
int rotate(game_t *game, int side, int row, int col, rot_t dir);
|
||||||
|
int move(game_t *game, int side, int row, int col, int dir, int flags);
|
||||||
|
void place(game_t *game, int row, int col, int piece, int side, int dir);
|
||||||
|
void setup_board(game_t *game, char *desc);
|
||||||
|
void init_game(game_t *game);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
336
src/server.c
336
src/server.c
@ -6,39 +6,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "game.h"
|
||||||
#define NONE 0
|
#include "asciiart.h"
|
||||||
#define PHARAO 1
|
|
||||||
#define DJHED 2
|
|
||||||
#define PYRAMID 3
|
|
||||||
#define OBELISK 4
|
|
||||||
#define OBELISK2 5
|
|
||||||
|
|
||||||
#define N_PIECE_TYPES 6
|
|
||||||
|
|
||||||
#define SILVER 0
|
|
||||||
#define RED 1
|
|
||||||
|
|
||||||
#define F_ROTATE 1
|
|
||||||
#define F_SPLIT 2
|
|
||||||
|
|
||||||
#define BOARD_WIDTH 10
|
|
||||||
#define BOARD_HEIGHT 8
|
|
||||||
|
|
||||||
#define E_ILLEGAL_MOVE -1
|
|
||||||
#define E_UNKNOWN_COMMAND -2
|
|
||||||
#define HUGE_SUCCESS 1
|
|
||||||
|
|
||||||
// return values for laser():
|
|
||||||
#define L_WALL 0
|
|
||||||
#define L_PIECE 1
|
|
||||||
#define SILVER_WINS 2
|
|
||||||
#define RED_WINS 3
|
|
||||||
|
|
||||||
#define MAX_MSG_LEN 50
|
#define MAX_MSG_LEN 50
|
||||||
typedef enum { MSG_MOVE, MSG_ROTATE } move_t;
|
typedef enum { MSG_MOVE, MSG_ROTATE } move_t;
|
||||||
typedef enum { R_CW, R_CCW } rot_t;
|
|
||||||
typedef enum { D_NW=0, D_N, D_NE, D_E, D_SE, D_S, D_SW, D_W } dir_t;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
move_t type;
|
move_t type;
|
||||||
@ -54,73 +26,9 @@ typedef struct {
|
|||||||
} args;
|
} args;
|
||||||
} message_t;
|
} message_t;
|
||||||
|
|
||||||
struct pieceinfo {
|
|
||||||
int num;
|
|
||||||
} pieceinfo[] = {
|
|
||||||
{ // NONE
|
|
||||||
.num = 0 },
|
|
||||||
{ // PHARAO
|
|
||||||
.num = 1 },
|
|
||||||
{ // DJHED
|
|
||||||
.num = 2 },
|
|
||||||
{ // PYRAMID
|
|
||||||
.num = 7 },
|
|
||||||
{ // OBELISK
|
|
||||||
.num = 4 },
|
|
||||||
{ // OBELISK2
|
|
||||||
.num = 0 },
|
|
||||||
};
|
|
||||||
|
|
||||||
struct square {
|
|
||||||
unsigned int piece : 4;
|
|
||||||
unsigned int side : 1;
|
|
||||||
unsigned int dir : 2;
|
|
||||||
} board[BOARD_WIDTH][BOARD_HEIGHT];
|
|
||||||
|
|
||||||
int laser_pos[2];
|
|
||||||
|
|
||||||
struct sideinfo {
|
|
||||||
char ch;
|
|
||||||
char *name;
|
|
||||||
} sideinfo[] = {
|
|
||||||
{ .ch = 'o', .name = "silver" },
|
|
||||||
{ .ch = 'x', .name = "red" } };
|
|
||||||
|
|
||||||
char classic_setup[] =
|
|
||||||
"H40" // PHARAO
|
|
||||||
"E40E51" // DJHED
|
|
||||||
"H22G73E22D21E91D92C32" // PYRAMID
|
|
||||||
"H30H30H50H50" // OBELISK
|
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
char asciiart_small_pieces[] =
|
|
||||||
" " // NONE
|
|
||||||
"SSSSSSSSRRRRRRRR"
|
|
||||||
",'`.,'`..\"\"..\"\"." // DJHED
|
|
||||||
"`/\\'/.,\\\"/\\\"/==\\" // PYRAMID
|
|
||||||
". . . . = = = = " // OBELISK
|
|
||||||
"........========" // OBELISK2
|
|
||||||
;
|
|
||||||
|
|
||||||
void
|
|
||||||
print_piece_small(int piece, int side, int dir)
|
|
||||||
{
|
|
||||||
int index = (piece*4*2 + side*4 + dir) * 2;
|
|
||||||
net_all_printf("%c%c",
|
|
||||||
asciiart_small_pieces[index],
|
|
||||||
asciiart_small_pieces[index+1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
laser_at(int x, int y)
|
|
||||||
{
|
|
||||||
return laser_pos[0] == x && laser_pos[1] == y;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME rewrite this to format the board in a char *?
|
// FIXME rewrite this to format the board in a char *?
|
||||||
|
/*
|
||||||
void
|
void
|
||||||
print_board_small()
|
print_board_small()
|
||||||
{
|
{
|
||||||
@ -185,212 +93,8 @@ print_board_small()
|
|||||||
net_all_printf(" ");
|
net_all_printf(" ");
|
||||||
net_all_printf("%s(%c)\n", sideinfo[SILVER].name, sideinfo[SILVER].ch);
|
net_all_printf("%s(%c)\n", sideinfo[SILVER].name, sideinfo[SILVER].ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
laser(int side) {
|
|
||||||
#define lreturn(v) do { retval=(v); goto ret; } while (0);
|
|
||||||
int x, y, dir;
|
|
||||||
int ddir;
|
|
||||||
int retval;
|
|
||||||
|
|
||||||
/*
|
|
||||||
dir:
|
|
||||||
0
|
|
||||||
3 X 1
|
|
||||||
2
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
net_all_printf("LASER (%s)\n", sideinfo[side].name);
|
|
||||||
|
|
||||||
assert(side == 0 || side == 1);
|
|
||||||
switch (side) {
|
|
||||||
case 0:
|
|
||||||
x=9; y=7; dir=0;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
x=0; y=0; dir=2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
net_all_printf("pos: (%d,%d)\n", y, x);
|
|
||||||
switch (board[x][y].piece) {
|
|
||||||
case NONE:
|
|
||||||
break;
|
|
||||||
case PHARAO:
|
|
||||||
lreturn(SILVER_WINS + 1-board[x][y].side); /* GAME OVER */
|
|
||||||
case OBELISK2:
|
|
||||||
board[x][y].piece = OBELISK;
|
|
||||||
lreturn(L_PIECE);
|
|
||||||
case OBELISK:
|
|
||||||
board[x][y].piece = NONE;
|
|
||||||
lreturn(L_PIECE);
|
|
||||||
case DJHED:
|
|
||||||
ddir = (board[x][y].dir - dir) & 3;
|
|
||||||
dir=(dir + 1 - 2*(ddir & 1)) & 3;
|
|
||||||
break;
|
|
||||||
case PYRAMID:
|
|
||||||
ddir = (board[x][y].dir - dir) & 3;
|
|
||||||
if (ddir & 2) {
|
|
||||||
board[x][y].piece = NONE;
|
|
||||||
lreturn(L_PIECE);
|
|
||||||
}
|
|
||||||
dir=(dir + 1 - 2*(ddir & 1)) & 3;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
switch (dir & 3) {
|
|
||||||
case 0: y--;
|
|
||||||
if (y<0) lreturn(L_WALL);
|
|
||||||
break;
|
|
||||||
case 1: x++;
|
|
||||||
if (x>BOARD_WIDTH-1) lreturn(L_WALL);
|
|
||||||
break;
|
|
||||||
case 2: y++;
|
|
||||||
if (y>BOARD_HEIGHT-1) lreturn(L_WALL);
|
|
||||||
break;
|
|
||||||
case 3: x--;
|
|
||||||
if (x<0) lreturn(L_WALL);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret:
|
|
||||||
laser_pos[0] = x;
|
|
||||||
laser_pos[1] = y;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
movable(int row, int col, int side)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
row>=0 && row<BOARD_HEIGHT &&
|
|
||||||
col>=0 && col<BOARD_WIDTH &&
|
|
||||||
board[col][row].piece != NONE &&
|
|
||||||
board[col][row].side == side;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
rotate(int side, int row, int col, rot_t dir)
|
|
||||||
{
|
|
||||||
int incr;
|
|
||||||
|
|
||||||
if (!movable(row, col, side))
|
|
||||||
return E_ILLEGAL_MOVE;
|
|
||||||
|
|
||||||
assert(dir==R_CW || dir==R_CCW);
|
|
||||||
|
|
||||||
incr = dir==R_CW ? 1 : -1;
|
|
||||||
board[col][row].dir = (board[col][row].dir + incr) & 3;
|
|
||||||
return HUGE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
move(int side, int row, int col, int dir, int flags) {
|
|
||||||
if (!movable(row, col, side))
|
|
||||||
return E_ILLEGAL_MOVE;
|
|
||||||
|
|
||||||
/* dir =
|
|
||||||
0 1 2
|
|
||||||
7 X 3
|
|
||||||
6 5 4
|
|
||||||
*/
|
|
||||||
|
|
||||||
assert((dir>=0) || (dir<=7));
|
|
||||||
int nrow = row - (dir<3) + ((dir>3) && (dir<7));
|
|
||||||
int ncol = col + ((dir>1) && (dir<5)) - ((dir<1) || (dir>5));
|
|
||||||
if ((ncol<0) || (ncol>9) || (nrow<0) || (nrow>7))
|
|
||||||
return E_ILLEGAL_MOVE;
|
|
||||||
|
|
||||||
if (flags & F_SPLIT) {
|
|
||||||
if (board[ncol][nrow].piece || (board[col][row].piece != OBELISK2))
|
|
||||||
return E_ILLEGAL_MOVE;
|
|
||||||
board[col][row].piece = OBELISK;
|
|
||||||
board[ncol][nrow].piece = OBELISK;
|
|
||||||
board[ncol][nrow].side = board[col][row].side;
|
|
||||||
return HUGE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (board[ncol][nrow].piece &&
|
|
||||||
!((board[col][row].piece == DJHED) &&
|
|
||||||
((board[ncol][nrow].piece != DJHED) &&
|
|
||||||
(board[ncol][nrow].piece != PHARAO))))
|
|
||||||
return E_ILLEGAL_MOVE;
|
|
||||||
|
|
||||||
struct square tmp;
|
|
||||||
tmp = board[ncol][nrow];
|
|
||||||
board[ncol][nrow] = board[col][row];
|
|
||||||
board[col][row] = tmp;
|
|
||||||
|
|
||||||
return HUGE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
place(int row, int col, int piece, int side, int dir)
|
|
||||||
{
|
|
||||||
if (board[col][row].piece == OBELISK &&
|
|
||||||
board[col][row].side == side &&
|
|
||||||
piece == OBELISK) {
|
|
||||||
piece = OBELISK2;
|
|
||||||
} else if (board[col][row].piece != NONE &&
|
|
||||||
piece != NONE) {
|
|
||||||
fprintf(stderr, "error: trying to place a piece on a non-empty square\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
board[col][row].piece = piece;
|
|
||||||
board[col][row].side = side;
|
|
||||||
board[col][row].dir = dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
clear_board()
|
|
||||||
{
|
|
||||||
int i, j;
|
|
||||||
for (i = 0; i < BOARD_HEIGHT; i++)
|
|
||||||
for (j = 0; j < BOARD_WIDTH; j++)
|
|
||||||
place(i, j, 0, 0, 0);
|
|
||||||
laser_pos[0] = laser_pos[1] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
setup_board_place_piece(int piece, int side, char *place_desc)
|
|
||||||
{
|
|
||||||
int row, col, dir;
|
|
||||||
|
|
||||||
row = place_desc[0]-'A';
|
|
||||||
col = place_desc[1]-'0';
|
|
||||||
dir = place_desc[2]-'0';
|
|
||||||
|
|
||||||
if (side == 1) {
|
|
||||||
row = BOARD_HEIGHT-row-1;
|
|
||||||
col = BOARD_WIDTH-col-1;
|
|
||||||
dir = (dir+2)&3;
|
|
||||||
}
|
|
||||||
|
|
||||||
place(row, col, piece, side, dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
setup_board(char *desc)
|
|
||||||
{
|
|
||||||
int side, piece, num, i;
|
|
||||||
|
|
||||||
clear_board();
|
|
||||||
|
|
||||||
for (side = 0; side < 2; side++) {
|
|
||||||
i = 0;
|
|
||||||
for (piece = 0; piece < N_PIECE_TYPES; piece++) {
|
|
||||||
for (num = 0; num < pieceinfo[piece].num; num++) {
|
|
||||||
setup_board_place_piece(piece, side,
|
|
||||||
&desc[i*3]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
read_message(int side, message_t *m)
|
read_message(int side, message_t *m)
|
||||||
{
|
{
|
||||||
@ -443,14 +147,16 @@ read_message(int side, message_t *m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
execute_message(message_t msg, int side)
|
execute_message(game_t *game, message_t msg, int side)
|
||||||
{
|
{
|
||||||
switch (msg.type) {
|
switch (msg.type) {
|
||||||
case MSG_MOVE:
|
case MSG_MOVE:
|
||||||
return move(side, msg.args.move.row, msg.args.move.col,
|
return move(game, side,
|
||||||
|
msg.args.move.row, msg.args.move.col,
|
||||||
msg.args.move.dir, 0);
|
msg.args.move.dir, 0);
|
||||||
case MSG_ROTATE:
|
case MSG_ROTATE:
|
||||||
return rotate(side, msg.args.rotate.row, msg.args.rotate.col,
|
return rotate(game, side,
|
||||||
|
msg.args.rotate.row, msg.args.rotate.col,
|
||||||
msg.args.rotate.dir);
|
msg.args.rotate.dir);
|
||||||
default:
|
default:
|
||||||
net_side_printf(side, "unknown command type %d\n", msg.type);
|
net_side_printf(side, "unknown command type %d\n", msg.type);
|
||||||
@ -459,12 +165,18 @@ execute_message(message_t msg, int side)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
simple_game()
|
simple_game(void)
|
||||||
{
|
{
|
||||||
int side = 0;
|
int side = 0;
|
||||||
|
|
||||||
setup_board(classic_setup);
|
game_t game;
|
||||||
print_board_small();
|
char aabuf[ASCIIART_SMALL_BUFSZ];
|
||||||
|
|
||||||
|
init_game(&game);
|
||||||
|
setup_board(&game, classic_setup);
|
||||||
|
asciiart_small_draw_board(aabuf, &game);
|
||||||
|
net_all_printf("%s", aabuf);
|
||||||
|
//print_board_small();
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
message_t msg;
|
message_t msg;
|
||||||
@ -486,12 +198,16 @@ simple_game()
|
|||||||
goto prompt;
|
goto prompt;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = execute_message(msg, side);
|
r = execute_message(&game, msg, side);
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case HUGE_SUCCESS:
|
case HUGE_SUCCESS:
|
||||||
print_board_small();
|
//print_board_small();
|
||||||
r = laser(side);
|
asciiart_small_draw_board(aabuf, &game);
|
||||||
print_board_small();
|
net_all_printf("%s", aabuf);
|
||||||
|
r = laser(&game, side);
|
||||||
|
//print_board_small();
|
||||||
|
asciiart_small_draw_board(aabuf, &game);
|
||||||
|
net_all_printf("%s", aabuf);
|
||||||
switch (r) {
|
switch (r) {
|
||||||
case SILVER_WINS:
|
case SILVER_WINS:
|
||||||
net_all_printf("SILVER WINS\n");
|
net_all_printf("SILVER WINS\n");
|
||||||
@ -503,7 +219,7 @@ simple_game()
|
|||||||
case L_PIECE:
|
case L_PIECE:
|
||||||
net_all_printf("laser hits %s at %c%c\n",
|
net_all_printf("laser hits %s at %c%c\n",
|
||||||
r==L_WALL ? "wall" : "piece",
|
r==L_WALL ? "wall" : "piece",
|
||||||
laser_pos[1]+'A', laser_pos[0]+'0');
|
game.laser_pos[1]+'A', game.laser_pos[0]+'0');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
side = 1-side;
|
side = 1-side;
|
||||||
|
Reference in New Issue
Block a user