264 lines
5.4 KiB
C
264 lines
5.4 KiB
C
/* -*- c-basic-offset: 4 -*- */
|
|
|
|
#include <assert.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "net.h"
|
|
#include "game.h"
|
|
|
|
pieceinfo_t pieceinfo[] = {
|
|
{ // NONE
|
|
.num = 0,
|
|
.name = "" },
|
|
{
|
|
.num = 1,
|
|
.name = "pharao" },
|
|
{ // DJHED
|
|
.num = 2,
|
|
.name = "djhed" },
|
|
{ // PYRAMID
|
|
.num = 7,
|
|
.name = "pyramid" },
|
|
{ // OBELISK
|
|
.num = 4,
|
|
.name = "obelisk" },
|
|
{ // OBELISK2
|
|
.num = 0,
|
|
.name = "stacked obelisk" },
|
|
};
|
|
|
|
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:
|
|
game->last_hit = game->board[x][y];
|
|
lreturn(SILVER_WINS + 1-game->board[x][y].side); /* GAME OVER */
|
|
case OBELISK2:
|
|
game->last_hit = game->board[x][y];
|
|
game->board[x][y].piece = OBELISK;
|
|
lreturn(L_PIECE);
|
|
case OBELISK:
|
|
game->last_hit = game->board[x][y];
|
|
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->last_hit = game->board[x][y];
|
|
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);
|
|
}
|
|
|