X-Git-Url: http://git.shiar.net/netris.git/blobdiff_plain/314fb8c12b376d5e9bc62ec8b5db9458618a162b..93d1d285b606413a0c60905f8b43389661ac30ec:/client.c diff --git a/client.c b/client.c index a1e284d..926c08b 100644 --- a/client.c +++ b/client.c @@ -21,6 +21,7 @@ #include "netris.h" #include +#include #include #include #include @@ -40,7 +41,6 @@ static struct option options[] = { { "level", 1, 0, 'l' }, { "nick", 1, 0, 'n' }, { "team", 1, 0, 't' }, - { "dropmode", 2, 0, 'd' }, { "color", 2, 0, 'C' }, { "slowterm", 2, 0, 'S' }, { "keys", 1, 0, 'k' }, @@ -51,12 +51,12 @@ static struct option options[] = { }; enum { - KT_left, KT_right, KT_rotright, KT_rotleft, KT_drop, KT_down, + KT_left, KT_right, KT_rotright, KT_rotleft, KT_drop, KT_dropsoft, KT_down, KT_faster, KT_pause, KT_redraw, KT_say, KT_quit, KT_numKeys }; static char *keyNames[KT_numKeys+1] = { - "Left", "Right", "RotRight", "RotLeft", "Drop", "Down", + "Left", "Right", "RotRight", "RotLeft", "Drop", "DropSoft", "Down", "Faster", "Pause", "Redraw", "Say", "Quit", NULL }; @@ -64,12 +64,20 @@ _Sets Sets = {7, 0, 1, 1, 1}; static char keyTable[KT_numKeys+1]; +enum { + CT_quit, CT_pause, + CT_MAX +}; +static char *cmds[] = { + "quit", "pause" +}; + static char *hostStr; -static int paused = 0; +static bool paused = 0; static char lastadd; -void MapKeys(char *newKeys) +void handle_setkeys(char *newKeys) { int i, k, ch; char used[256]; @@ -125,8 +133,6 @@ void Usage(void) " -t, --team \tJoin a team (don't receive lines from your teammates)\n" " -l, --level \tBegin at a higher level (can be used as handicap)\n" " -k, --keys \tRemap keys (default is \"%s\" for cursors)\n" - " -d, --dropmode\tDrops go into drop mode\n" - " -D, --instadrop\tInstant drop\n" "\n" " -r, --robot \tExecute program to control the game instead of keyboard\n" " -F, --fair-robot\tUse fair robot interface\n" @@ -135,7 +141,7 @@ void Usage(void) ); } -void HandleOption(char tag, char *value) +void handle_arg(char tag, char *value) { switch (tag) { case 'a': //ascii @@ -143,7 +149,7 @@ void HandleOption(char tag, char *value) Sets.drawstyle &= ~Sets.ascii; break; case 'c': //connect - game = GT_classicTwo; + Game.type = GT_classicTwo; hostStr = value; break; case 'p': //port @@ -161,9 +167,6 @@ void HandleOption(char tag, char *value) case 't': //team Players[0].team = atoi(value); break; - case 'd': //dropmode - Sets.dropmode = value ? atoi(value) : 1; - break; case 'C': //color Sets.color = value && strcasecmp(value, "0") ? 1 : 0; break; @@ -171,7 +174,7 @@ void HandleOption(char tag, char *value) Sets.standout = value && !strcasecmp(value, "0") ? 1 : 0; break; case 'k': //keys - MapKeys(value); + handle_setkeys(value); break; case 'H': //info Header(); @@ -189,7 +192,7 @@ void HandleOption(char tag, char *value) } } -void ReadConf(char *filename) +void handle_conffile(char *filename) { FILE *file_in; char buf[513]; @@ -210,7 +213,7 @@ void ReadConf(char *filename) sscanf(buf, "%80[^= \t] = %80[^\n]", tag, value); for (i = 0; options[i].name; i++){ if (!strcasecmp(options[i].name, tag)) { - HandleOption(options[i].val, value); + handle_arg(options[i].val, value); break; } } @@ -220,10 +223,9 @@ void ReadConf(char *filename) else { fprintf(stderr, "Unable to open config file %s.\n", filename); } //defaults - } -int StartNewPiece(int scr, char shape) +int game_piece(int scr, char shape) { Players[scr].score.pieces++; { @@ -243,17 +245,16 @@ int StartNewPiece(int scr, char shape) return 1; } -void checkPaused(void) +void game_setpaused(void) { //check whether anyone paused the game int i; paused = Game.started < 1; for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive > 0) - paused |= Players[i].flags & SCF_paused; - if (paused) paused = 1; + paused |= (Players[i].flags & SCF_paused) != 0; } -void StartGame(void) +void game_reset(void) { //init new game int i; @@ -276,7 +277,7 @@ void StartGame(void) InitFields(); } -void CheckClears(int scr) +void game_clear(int scr) { //check for full lines int linesCleared; int linevalues[] = { 40, 100, 400, 1200, }; //= 50*lines! - 10*(lines==1) @@ -286,7 +287,7 @@ void CheckClears(int scr) 2500, 3000, 3500, 4000, 4500, 5000, 6000, 7500 }; if ((linesCleared = ClearFullLines(scr)) > 0) { - if (game == GT_onePlayer) + if (Game.type == GT_onePlayer) if ((Players[scr].score.lines / 10) < ((Players[scr].score.lines+linesCleared)/10)) { if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM) @@ -297,9 +298,9 @@ void CheckClears(int scr) Players[scr].score.score += Game.gravity ? linevaluesq[linesCleared - 1] : linevalues[linesCleared - 1]; Players[scr].score.lines += linesCleared; - Players[scr].score.adds += linesCleared - (linesCleared < 4); + Players[scr].score.adds += linesCleared - (linesCleared < 4); //XXX match handicap if (scr == me) { - if (game == GT_classicTwo) { + if (Game.type == GT_classicTwo) { SendPacket(scr, NP_clear, 0, NULL); if (linesCleared > 1) { short junkLines; @@ -320,15 +321,76 @@ void CheckClears(int scr) } //lines cleared } -void OneGame(void) +void game_loop(void) { - int changed = 0; + bool changed = 0; short gameStatus = 2; //2=loop; 1=new piece; 0=quit - int dropMode = 0; - int chatMode = 0; + bool chatMode = 0; char chatText[MSG_WIDTH] = "\0"; - void GameKey(char key) + void handle_cmd(char cmd, char *arg) + { + switch (cmd) { + case CT_quit: + ShowPause(me); + refresh(); + gameStatus = 0; + return; + case CT_pause: + if (Players[me].alive <= 0) return; + Players[me].flags ^= SCF_paused; + if (Game.started > 1) + Message(Players[me].flags & SCF_paused + ? "You paused the game" : "You unpaused the game"); + else + Message(Players[me].flags & SCF_paused + ? "You are not ready" : "You are ready"); + game_setpaused(); + if (Game.type == GT_classicTwo) + SendPacket(me, NP_pause, 0, NULL); + ShowPause(me); + changed = 1; + return; + } + } + + void handle_cmdstr(char *cmd) + { + char tag[17], value[81]; + char *cmdend; + int i; + + if ((cmdend = strchr(cmd, ' '))) { + *cmdend = 0; + } else { + cmdend = cmd + strlen(cmd); // whole string + } + for (i = 0; i < CT_MAX; i++){ + if (!strcasecmp(cmds[i], cmd)) { + return handle_cmd(i, cmdend + 1); + } + } + Message("Unknown command /%s", cmd); + } + + void handle_str(char *str) + { + if (chatText[0] == '/') { + if (chatText[1] != '/') { + handle_cmdstr(chatText + 1); + return; + } + memmove(chatText, chatText + 1, strlen(chatText)); + } + + Message("<\\%d%s\\7> %s", + Players[me].team > 7 ? 7 : Players[me].team, + Players[me].name, chatText); + if (Game.type == GT_classicTwo) + SendPacket(me, NP_msg, strlen(chatText) + 1, chatText); + } + + void handle_key(char key) { char *p; @@ -337,11 +399,7 @@ void OneGame(void) // enter text chatMode = 0; if (chatText[0]) { - Message("<\\%d%s\\7> %s", - Players[me].team > 7 ? 7 : Players[me].team, - Players[me].name, chatText); - if (game == GT_classicTwo) - SendPacket(me, NP_msg, strlen(chatText) + 1, chatText); + handle_str(chatText); memset(chatText, 0, sizeof(chatText)); } //say it else Messagetype(27, -1, NULL); //escape @@ -360,7 +418,8 @@ void OneGame(void) if (!(p = strchr(keyTable, tolower(key)))) return; key = p - keyTable; - // global actions (always possible, even if not playing) + void handle_keycmd(char key) + { switch (key) { case KT_redraw: clear(); @@ -373,32 +432,14 @@ void OneGame(void) Messagetype(key, strlen(chatText) - 1, chatText); return; case KT_quit: - ShowPause(me); - refresh(); - gameStatus = 0; + handle_cmd(CT_quit, NULL); return; - } - - if (Players[me].alive <= 0) return; - // actions available while in game - switch (key) { case KT_pause: - Players[me].flags ^= SCF_paused; - if (Game.started > 1) - Message(Players[me].flags & SCF_paused - ? "You paused the game" : "You unpaused the game"); - else - Message(Players[me].flags & SCF_paused - ? "You are not ready" : "You are ready"); - checkPaused(); - if (game == GT_classicTwo) - SendPacket(me, NP_pause, 0, NULL); - ShowPause(me); - changed = 1; + handle_cmd(CT_pause, NULL); return; } - if (paused) return; + if (Players[me].alive <= 0 || paused) return; // actions only available while actually playing switch (key) { case KT_left: @@ -421,17 +462,22 @@ void OneGame(void) else gameStatus = 1; //completely dropped break; - case KT_drop: + case KT_dropsoft: SetITimer(Game.speed, Game.speed); if (DropPiece(me)) { if (spied) SendPacket(me, NP_drop, 0, NULL); - if (!Sets.dropmode) gameStatus = 1; //instadrop } else gameStatus = 1; //dropped - dropMode = Sets.dropmode > 1; + break; + case KT_drop: + SetITimer(Game.speed, Game.speed); + if (DropPiece(me)) { + if (spied) SendPacket(me, NP_drop, 0, NULL); + } + gameStatus = 1; // drop break; case KT_faster: - if (game != GT_onePlayer) break; + if (Game.type != GT_onePlayer) break; if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM) Game.speed = SPEEDMINIMUM; SetITimer(Game.speed, SetITimer(0, 0)); @@ -440,24 +486,20 @@ void OneGame(void) changed = 1; break; } - - if (dropMode && DropPiece(me) > 0) { - SetITimer(Game.speed, Game.speed); - if (spied) SendPacket(me, NP_drop, 0, NULL); - } - return; - } //GameKey + } + handle_keycmd(key); + } int oldPaused = 0; - void GameNet(_netEvent net) + void handle_net(_netEvent net) { switch(net.type) { case NP_newPiece: { memcpy(&Players[net.uid].nextShape, net.data, sizeof(Players[0].nextShape)); - StartNewPiece(net.uid, Players[net.uid].curShape); + game_piece(net.uid, Players[net.uid].curShape); break; } case NP_down: @@ -479,7 +521,7 @@ void OneGame(void) DropPiece(net.uid); break; case NP_clear: - CheckClears(net.uid); + game_clear(net.uid); break; case NP_insertJunk: { @@ -560,9 +602,9 @@ void OneGame(void) Players[i].flags |= SCF_paused; } //reset players } - StartGame(); //reset everything + game_reset(); //reset everything ShowTime(); //redraw timer while unpaused - checkPaused(); //pause + game_setpaused(); //pause oldPaused = 0; //reset pause changed = 1; gameStatus = 1; @@ -570,9 +612,6 @@ void OneGame(void) } //stop game case NP_newPlayer: { - char teams[10][7] = { "", "Green", "Cyan", "Blue", "Purple", - "Red", "Grey", "White", "*Orange" }; - if (net.uid>maxPlayer) maxPlayer = net.uid; memcpy(&Players[net.uid], net.data, net.size); ClearField(net.uid); @@ -581,9 +620,9 @@ void OneGame(void) Message("%s joined the game", Players[net.uid].name); else Message("%s joined %s team", Players[net.uid].name, - teams[Players[net.uid].team]); + teamname[Players[net.uid].team]); if (Players[net.uid].flags & SCF_paused) { - checkPaused(); + game_setpaused(); } //player has paused // DrawField(net.uid); // ShowPause(net.uid); @@ -602,18 +641,18 @@ void OneGame(void) strcpy(s, Players[net.uid].flags&SCF_paused ? "is not ready" : "is ready"); Message("%s %s", Players[net.uid].name, s); - checkPaused(); + game_setpaused(); ShowPause(net.uid); changed = 1; break; } //(un)pause case NP_part: // player left - checkPaused(); + game_setpaused(); oldPaused = 0; Players[net.uid].alive = -1; Message("%s left", Players[net.uid].name); - checkPaused(); + game_setpaused(); ShowPause(net.uid); changed = 1; break; @@ -632,34 +671,34 @@ void OneGame(void) Message("\\%d%s fragged %s", Players[i].team > 7 ? 7 : Players[i].team, Players[i].name, Players[net.uid].name); - checkPaused(); + game_setpaused(); ShowPause(net.uid); changed = 1; break; } //G/O default: break; - } //E_net - } //GameNet + } + } MyEvent event; long pauseTimeLeft; int i; - StartGame(); + game_reset(); while (gameStatus) { -GameLoop: gameStatus = 2; if (Players[me].alive > 0) { - if (!StartNewPiece(me, ChooseOption(stdOptions))) { - netint4 data[4]; + if (!game_piece(me, ChooseOption(stdOptions))) { + netint4 data[4]; + Players[me].alive = 0; if (lastadd == me) Message("\\%dYou died", Players[me].team > 7 ? 7 : Players[me].team); else Message("\\%d%s fragged you", Players[lastadd].team > 7 ? 7 : Players[lastadd].team, Players[lastadd].name); - if (game == GT_classicTwo) + if (Game.type == GT_classicTwo) SendPacket(me, NP_argghhh, sizeof(lastadd), &lastadd); ShowPause(me); changed = 1; @@ -695,10 +734,10 @@ GameLoop: if (spied) SendPacket(me, NP_down, 0, NULL); break; case E_key: - GameKey(event.u.key); + handle_key(event.u.key); break; case E_net: - GameNet(event.u.net); + handle_net(event.u.net); break; case E_lostConn: goto gameOver; @@ -715,9 +754,8 @@ GameLoop: oldPaused = paused; } //(un)pause } //game loop - dropMode = 0; Players[me].score.score++; - CheckClears(me); + game_clear(me); } //new piece loop gameOver: SetITimer(0, 0); @@ -727,12 +765,12 @@ int main(int argc, char **argv) { char ch; - game = GT_onePlayer; + Game.type = GT_onePlayer; port = DEFAULT_PORT; maxPlayer = 1; Game.initspeed = DEFAULT_INTERVAL; Game.gravity = 0; - MapKeys(DEFAULT_KEYS); + handle_setkeys(DEFAULT_KEYS); { int i; char *userName; @@ -752,17 +790,16 @@ int main(int argc, char **argv) strncpy(Players[0].name, userName, 16); //sizeof(Player.name) Players[0].name[16] = 0; Players[0].alive = 1; - Players[0].dropmode = 0; } //set defaults // if (getopt(argc, argv, "f:") == 'f') -// ReadConf(optarg); +// handle_conffile(optarg); // else - ReadConf(CONFIG_FILE); + handle_conffile(CONFIG_FILE); while ((ch = getopt_long( - argc, argv, "hHRk:c:n:odDSCap:i:l:t:", options, NULL + argc, argv, "hHRk:c:n:oSCap:i:l:t:", options, NULL )) != -1) - HandleOption(ch, optarg); + handle_arg(ch, optarg); if (optind < argc) { Usage(); exit(1); @@ -771,13 +808,13 @@ int main(int argc, char **argv) InitScreens(); //setup screen - if (game == GT_classicTwo) { + if (Game.type == GT_classicTwo) { spied = 1; InitiateConnection(hostStr, port); HandShake(); maxPlayer = me; - checkPaused(); - OneGame(); + game_setpaused(); + game_loop(); } //client else { Game.seed = time(0); @@ -785,7 +822,7 @@ int main(int argc, char **argv) me = 1; memcpy(&Players[me], &Players[0], sizeof(_Player)); Players[me].team = 7; - OneGame(); + game_loop(); } //singleplay return 0; }