SAI ||
Sommersemester 1997 ||
Systemnahe Software II ||
Übungen
<- Alle Module
Lösung zu Blatt 5 (Aufgabe 6): gbsess.h + gbsess.c
Steuerung einer Gobang-Sitzung.
/*
* gbsess.h - headerfile for Gobang session driver
*
* Martin Hasch, University of Ulm, June 1997
*/
typedef enum { CLIENT_BLACK, CLIENT_WHITE, CLIENT_KIBITZ } SessionMode;
/*
* Gobang session. (server_id) identifies server process.
*/
void session(SessionMode mode, int server_id);
/*
* gbsess.c - Gobang session driver
*
* Martin Hasch, University of Ulm, June 1997
*/
#include <stdio.h>
#include <stdlib.h>
#include "gbmesg.h"
#include "gbuser.h"
#include "gbdisp.h"
#include "gbsess.h"
static unsigned boardsize = 0;
static unsigned lastx = 0;
static unsigned lasty = 0;
/*
* First stage of a session: Establish connection and get board size.
*/
static void prepare(SessionMode mode, int server_id)
{
unsigned request;
Message message;
switch ( mode ) {
case CLIENT_BLACK:
request = RQ_SIGNON_BLACK;
printf("playing black stones\n");
break;
case CLIENT_WHITE:
request = RQ_SIGNON_WHITE;
printf("playing white stones\n");
break;
case CLIENT_KIBITZ:
request = RQ_SIGNON_KIBITZ;
printf("watching without playing\n");
break;
default:
abort(); /* should not happen */
}
printf("trying to contact server (id %d)\n", server_id);
if ( !mesg_init(server_id) || !mesg_sendrequest(request, 0, 0) ||
!mesg_receive(&message) ) {
printf("connection failed\n");
exit(1);
}
if ( message.m_code != MSG_SIZE ) {
printf("connection refused\n");
exit(1);
}
boardsize = message.m_y;
printf("connection established, board size %u\n", boardsize);
}
/*
* Transmission of a request. Returns only on success.
*/
static void send(code, x, y)
{
if ( !mesg_sendrequest(code, x, y) ) {
gb_status("connection broken");
exit(1);
}
}
/*
* Elicit a move from the user.
*/
static void getmove(void)
{
(void) gb_goto(lastx, lasty); /* switch cursor on */
for (;;) {
switch ( gb_getcommand() ) {
case GBU_QUIT:
send(RQ_RESIGN, 0, 0);
return;
case GBU_LEFT:
if ( gb_goto(lastx-1, lasty) == GB_OK )
--lastx;
break;
case GBU_DOWN:
if ( gb_goto(lastx, lasty-1) == GB_OK )
--lasty;
break;
case GBU_UP:
if ( gb_goto(lastx, lasty+1) == GB_OK )
++lasty;
break;
case GBU_RIGHT:
if ( gb_goto(lastx+1, lasty) == GB_OK )
++lastx;
break;
case GBU_REDRAW:
gb_redraw();
break;
case GBU_MOVE:
send(RQ_MOVE, lastx, lasty);
return;
case GBU_PASS:
send(RQ_MOVE, 0, 0);
return;
default:
/* ignore */
break;
}
}
}
/*
* Update screen and data structures when a move has been reported.
*/
static void do_move(unsigned x, unsigned y, int color)
{
if ( x || y ) { /* not a pass? */
lastx = x;
lasty = y;
gb_set(lastx, lasty, color);
}
if ( color == 1 || color == 2 )
gb_turn(1+2 - color);
}
/*
* Main loop: React (mostly) on server messages during the game.
*/
static void mainloop(void)
{
Message message;
int badmove;
badmove = 0;
for (;;) {
(void) gb_goto(0,0); /* hide cursor */
gb_status("waiting for remote action");
if ( !mesg_receive(&message) ) {
gb_status("connection broken");
exit(1);
}
switch ( message.m_code ) {
case MSG_DRAW:
gb_status("game is a draw!");
return;
case MSG_BLACK_WINS:
gb_status("winner is black!");
return;
case MSG_WHITE_WINS:
gb_status("winner is white!");
return;
case MSG_ABORT:
gb_status("game aborted!");
return;
case MSG_TOGGLE_EMPTY:
do_move(message.m_x, message.m_y, 0);
badmove = 0;
continue;
case MSG_TOGGLE_BLACK:
do_move(message.m_x, message.m_y, 1);
badmove = 0;
continue;
case MSG_TOGGLE_WHITE:
do_move(message.m_x, message.m_y, 2);
badmove = 0;
continue;
case MSG_YOUR_TURN:
if ( badmove )
gb_status("illegal move, try again");
else
gb_status("enter your move");
break;
case MSG_ILLEGAL_MOVE:
badmove = 1;
continue;
default:
/* ignore rubbish */
continue;
}
getmove();
}
}
/*
* Gobang session. (server_id) identifies server process.
*/
void session(SessionMode mode, int server_id)
{
prepare(mode, server_id);
/*
* We enter graphical mode only after a connection to the
* server has been established.
*/
if ( gb_reset(boardsize) != GB_OK ) {
printf("cannot handle board size %u, sorry\n", boardsize);
(void) mesg_sendrequest(RQ_SIGNOFF, 0, 0);
exit(1);
}
lastx = lasty = (gb_size()+1) >> 1;
gb_turn(1);
mainloop();
}
<- Alle Module
SAI ||
Sommersemester 1997 ||
Systemnahe Software II ||
Übungen
Martin Hasch, Juni 1997