X-Git-Url: http://git.shiar.net/netris.git/blobdiff_plain/21add7c13bc1df386e45aad2939ee5ff2a152c2b..4f561019fc85c2817e3a72341397d1df32bc0868:/game.c diff --git a/game.c b/game.c index 07dda94..b88e05d 100644 --- a/game.c +++ b/game.c @@ -26,6 +26,7 @@ #include #include #include +#include static struct option options[] = { { "ascii", 2, 0, 'a' }, @@ -61,6 +62,8 @@ static char keyTable[KT_numKeys+1]; static char *hostStr; static int paused = 0; +static sigjmp_buf close_env; + ExtFunc void MapKeys(char *newKeys) { @@ -233,7 +236,7 @@ ExtFunc int StartNewPiece(int scr, Shape *shape) Players[scr].curY, Players[scr].curX)) return 0; PlotShape(Players[scr].curShape, scr, - Players[scr].curY, Players[scr].curX, 1); + Players[scr].curY, Players[scr].curX, 1, 1); return 1; } @@ -241,103 +244,113 @@ ExtFunc void checkPaused(void) { //check whether anyone paused the game int i; - paused = 0; - for (i = 1; i <= totalPlayers; i++) - if (Players[i].alive) - paused |= Players[i].flags & SCF_paused; + paused = Game.started < 1; + for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive) + paused |= Players[i].flags & SCF_paused; + if (paused) paused = 1; + else if (Game.started == 1) { + Game.started = 2; + Messagef("The game has started"); + for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive) + ShowPause(i); + } //everybody ready } //checkPaused -ExtFunc void OneGame(int scr) +ExtFunc void OneGame(void) { MyEvent event; int linesCleared, changed = 0; - int spied = 0, dropMode = 0; + int dropMode = 0; int oldPaused = 0; long pauseTimeLeft; int pieceCount = 0; int key; char *p, *cmd; int playercount; + char lastadd; int linevalues[4] = { 40, 100, 400, 1200 }; //= 50*lines! - 10*(lines==1) int i; + maxPlayer = lastadd = me; Game.speed = Game.initspeed; - for (i = 1; i < Players[scr].score.level; i++) + for (i = 1; i < Players[me].score.level; i++) Game.speed /= SPEEDINC; if (Game.speed < SPEEDMINIMUM) Game.speed = SPEEDMINIMUM; - ResetBaseTime(); + ResetBaseTime(); //reset timer + ClearField(me); InitFields(); - for (i = 1; i <= totalPlayers; i++) - if (Players[i].spy) DrawField(i); - if (totalPlayers > 1) { - spied = 1; - } SetITimer(Game.speed, Game.speed); if (robotEnable) { + int counter; RobotCmd(0, "GameType %s\n", gameNames[game]); RobotCmd(0, "BoardSize 0 %d %d\n", - Players[scr].boardVisible, Players[scr].boardWidth); - for (i = 1; i <= totalPlayers; i++) { + Players[me].boardVisible, Players[me].boardWidth); + for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive && i != me) { RobotCmd(0, "BoardSize %d %d %d\n", - i, Players[i].boardVisible, Players[i].boardWidth); + counter, Players[i].boardVisible, Players[i].boardWidth); RobotCmd(0, "Opponent %d %s %s\n", - i, Players[i].name, Players[i].host); + counter, Players[i].name, Players[i].host); if (Players[i].flags & SCF_usingRobot) RobotCmd(0, "OpponentFlag %d robot\n", i); if (Players[i].flags & SCF_fairRobot) RobotCmd(0, "OpponentFlag %d fairRobot\n", i); + counter++; } RobotCmd(0, "TickLength %.3f\n", Game.speed / 1.0e6); RobotCmd(0, "BeginGame\n"); RobotTimeStamp(); } - Players[scr].nextShape = ChooseOption(stdOptions); + Players[me].nextShape = ChooseOption(stdOptions); while (1) { - if (Players[scr].alive) { - if (!StartNewPiece(scr, ChooseOption(stdOptions))) { + if (Players[me].alive) { + if (!StartNewPiece(me, ChooseOption(stdOptions))) { netint4 data[4]; - Players[scr].alive = 0; - FieldMessage(scr, "G A M E O V E R"); - changed = 1; + Players[me].alive = 0; + if (lastadd == me) Messagef("You died"); + else Messagef("\\%d%s fragged you", + Players[lastadd].team > 7 ? 7 : Players[lastadd].team, + Players[lastadd].name); if (game == GT_classicTwo) - SendPacket(scr, NP_argghhh, - sizeof(Players[0].alive), &Players[scr].alive); + SendPacket(me, NP_argghhh, sizeof(lastadd), &lastadd); + ShowPause(me); + changed = 1; } //die else { - ShowScore(scr, Players[scr].score); + ShowScore(me, Players[me].score); if (robotEnable && !fairRobot) RobotCmd(1, "NewPiece %d\n", ++pieceCount); if (spied) { short shapeNum; netint2 data[1]; - shapeNum = ShapeToNetNum(Players[scr].curShape); + shapeNum = ShapeToNetNum(Players[me].curShape); data[0] = hton2(shapeNum); - SendPacket(scr, NP_newPiece, sizeof(data), data); + SendPacket(me, NP_newPiece, sizeof(data), data); } //send new piece } - } - for (;;) { - for (i = 1; i <= totalPlayers; i++) if (Players[i].spy) - changed |= RefreshBoard(i); + } //new piece + while (1) { + for (i = 1; i < MAX_SCREENS; i++) + if (Players[i].alive && Players[i].spy) + changed |= RefreshBoard(i); if (changed) { if (!paused) ShowTime(); refresh(); changed = 0; - } + } //screen update playercount = 0; - for (i = 1; i <= totalPlayers; i++) + for (i = 1; i < MAX_SCREENS; i++) if (Players[i].alive) playercount++; - if (playercount < game + 1) goto gameOver; + if (playercount < 1) goto gameOver; CheckNetConn(); switch (WaitMyEvent(&event, EM_any)) { case E_alarm: - if (Players[scr].alive) - if (!MovePiece(scr, -1, 0)) + if (!paused && Players[me].alive) + if (!MovePiece(me, -1, 0)) goto nextPiece; else if (spied) - SendPacket(scr, NP_down, 0, NULL); + SendPacket(me, NP_down, 0, NULL); break; case E_key: p = strchr(keyTable, tolower(event.u.key)); @@ -350,49 +363,40 @@ ExtFunc void OneGame(int scr) } //let robot handle keypress if (!p) break; keyEvent: - if (!Players[scr].alive && key != KT_quit) break; + if (!Players[me].alive && key != KT_quit) break; if (paused && key < KT_pause) break; switch(key) { case KT_left: - if (MovePiece(scr, 0, -1) && spied) - SendPacket(scr, NP_left, 0, NULL); + if (MovePiece(me, 0, -1) && spied) + SendPacket(me, NP_left, 0, NULL); break; case KT_right: - if (MovePiece(scr, 0, 1) && spied) - SendPacket(scr, NP_right, 0, NULL); + if (MovePiece(me, 0, 1) && spied) + SendPacket(me, NP_right, 0, NULL); break; case KT_rotleft: - if (RotatePiece(scr, 0) && spied) - SendPacket(scr, NP_rotleft, 0, NULL); + if (RotatePiece(me, 0) && spied) + SendPacket(me, NP_rotleft, 0, NULL); break; case KT_rotright: - if (RotatePiece(scr, 1) && spied) - SendPacket(scr, NP_rotright, 0, NULL); + if (RotatePiece(me, 1) && spied) + SendPacket(me, NP_rotright, 0, NULL); break; case KT_down: SetITimer(Game.speed, Game.speed); - if (MovePiece(scr, -1, 0)) { - if (spied) SendPacket(scr, NP_down, 0, NULL); + if (MovePiece(me, -1, 0)) { + if (spied) SendPacket(me, NP_down, 0, NULL); } else goto nextPiece; break; case KT_drop: SetITimer(Game.speed, Game.speed); - if (DropPiece(scr)) { - if (spied) SendPacket(scr, NP_drop, 0, NULL); - if (Players[scr].dropmode == 2) goto nextPiece; + if (DropPiece(me)) { + if (spied) SendPacket(me, NP_drop, 0, NULL); + if (Players[me].dropmode == 2) goto nextPiece; } else goto nextPiece; - dropMode = Players[scr].dropmode; - break; - case KT_pause: - Players[scr].flags ^= SCF_paused; - checkPaused(); - if (game == GT_classicTwo) - SendPacket(scr, NP_pause, 0, NULL); - if (robotEnable) RobotCmd(1, "Pause %d\n", paused); - ShowPause(scr); - changed = 1; + dropMode = Players[me].dropmode; break; case KT_faster: if (game != GT_onePlayer) @@ -400,24 +404,44 @@ ExtFunc void OneGame(int scr) if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM) Game.speed = SPEEDMINIMUM; SetITimer(Game.speed, SetITimer(0, 0)); - Players[scr].score.level++; - ShowScore(scr, Players[scr].score); + Players[me].score.level++; + ShowScore(me, Players[me].score); + changed = 1; + break; + case KT_pause: + Players[me].flags ^= SCF_paused; + if (Game.started > 1) + Messagef(Players[me].flags & SCF_paused + ? "You paused the game" + : "You unpaused the game"); + else + Messagef(Players[me].flags & SCF_paused + ? "You are not ready" : "You are ready"); + checkPaused(); + if (game == GT_classicTwo) + SendPacket(me, NP_pause, 0, NULL); + if (robotEnable) RobotCmd(1, "Pause %d\n", paused); + ShowPause(me); changed = 1; break; case KT_redraw: - ScheduleFullRedraw(); -// if (paused) -// RefreshScreen(); + DrawTitle(); + InitFields(); +// ScheduleFullRedraw(); + for (i = 1; i < MAX_SCREENS; i++) + if (Players[i].alive && Players[i].spy) + RefreshBoard(i); + refresh(); break; case KT_quit: - FieldMessage(me, "G A M E O V E R"); + ShowPause(me); refresh(); goto gameOver; } //E_key - if (dropMode && DropPiece(scr) > 0) { + if (dropMode && DropPiece(me) > 0) { SetITimer(Game.speed, Game.speed); if (spied) - SendPacket(scr, NP_drop, 0, NULL); + SendPacket(me, NP_drop, 0, NULL); } break; case E_robot: @@ -435,28 +459,13 @@ ExtFunc void OneGame(int scr) num == pieceCount))) goto keyEvent; if (!strcmp(cmd, "Message")) { - Message(p); + Messagef(p); changed = 1; } break; } //E_robot case E_net: switch(event.u.net.type) { - case NP_giveJunk: - { - netint2 data[2]; - short column; - - if (!Players[scr].alive) break; - memcpy(data, event.u.net.data, sizeof(data[0])); - column = Random(0, Players[scr].boardWidth); - data[1] = hton2(column); - InsertJunk(scr, ntoh2(data[0]), column); - if (spied) - SendPacket(scr, NP_insertJunk, sizeof(data), data); -// Message("Opponent added %d lines"); - break; - } //receive junklines case NP_newPiece: { short shapeNum; @@ -465,7 +474,8 @@ ExtFunc void OneGame(int scr) FreezePiece(event.u.net.uid); memcpy(data, event.u.net.data, sizeof(data)); shapeNum = ntoh2(data[0]); - StartNewPiece(event.u.net.uid, NetNumToShape(shapeNum)); + StartNewPiece(event.u.net.uid, + NetNumToShape(shapeNum)); break; } //new piece case NP_down: @@ -494,12 +504,74 @@ ExtFunc void OneGame(int scr) netint2 data[2]; memcpy(data, event.u.net.data, sizeof(data)); - InsertJunk(event.u.net.uid, ntoh2(data[0]), ntoh2(data[1])); + InsertJunk(event.u.net.uid, ntoh2(data[0]), + ntoh2(data[1])); break; } //player added junklines + case NP_giveJunk: + { + netint2 data[2]; + short column; + + if (!Players[me].alive) break; + memcpy(data, event.u.net.data, sizeof(data[0])); + column = Random(0, Players[me].boardWidth); + data[1] = hton2(column); + Messagef("\\%d%s sends %d lines", + Players[event.u.net.uid].team > 7 ? 7 + : Players[event.u.net.uid].team, + Players[event.u.net.uid].name, ntoh2(data[0])); + lastadd = event.u.net.uid; + InsertJunk(me, ntoh2(data[0]), column); + if (spied) + SendPacket(me, NP_insertJunk, sizeof(data), + data); + break; + } //receive junklines + case NP_start: + { + Game.started = 1; + checkPaused(); + break; + } //start game + case NP_newPlayer: + { + if (event.u.net.uid > maxPlayer) + maxPlayer = event.u.net.uid; + memcpy(&Players[event.u.net.uid], + event.u.net.data, event.u.net.size); + ClearField(event.u.net.uid); + Messagef("\\%d%s joins the game", + Players[event.u.net.uid].team > 7 ? 7 + : Players[event.u.net.uid].team, + Players[event.u.net.uid].name); + if (Players[event.u.net.uid].flags & SCF_paused) { + checkPaused(); + if (robotEnable) + RobotCmd(1, "Pause %d\n", paused); + } //player has paused + DrawField(event.u.net.uid); +// ShowPause(event.u.net.uid); + changed = 1; + break; + } //player joined case NP_pause: { + char s[20]; + Players[event.u.net.uid].flags ^= SCF_paused; + if (Game.started > 1) + strcpy(s, + Players[event.u.net.uid].flags & SCF_paused + ? "paused the game" : "unpaused the game"); + else + strcpy(s, + Players[event.u.net.uid].flags & SCF_paused + ? "is not ready" : "is good to go"); + Messagef("\\%d%s %s", + Players[event.u.net.uid].team > 7 ? 7 + : Players[event.u.net.uid].team, + Players[event.u.net.uid].name, s); checkPaused(); if (robotEnable) RobotCmd(1, "Pause %d\n", paused); ShowPause(event.u.net.uid); @@ -508,10 +580,21 @@ ExtFunc void OneGame(int scr) } //(un)pause case NP_argghhh: { - memcpy(&Players[event.u.net.uid].alive, - event.u.net.data, sizeof(Players[0].alive)); -// checkPaused(); - FieldMessage(event.u.net.uid, "G A M E O V E R"); + char i; + memcpy(&i, event.u.net.data, sizeof(i)); + Players[event.u.net.uid].alive = 0; + if (i == me) Messagef("You fragged %s", + Players[event.u.net.uid].name); + else if (i == event.u.net.uid) + Messagef("\\%d%s died", + Players[i].team > 7 ? 7 : Players[i].team, + Players[i].name); + else Messagef("\\%d%s fragged %s", + Players[i].team > 7 ? 7 : Players[i].team, + Players[i].name, + Players[event.u.net.uid].name); + checkPaused(); + ShowPause(event.u.net.uid); changed = 1; break; } //G/O @@ -539,23 +622,23 @@ ExtFunc void OneGame(int scr) } //game loop nextPiece: dropMode = 0; - FreezePiece(scr); - Players[scr].score.drops++; - Players[scr].score.score++; - if ((linesCleared = ClearFullLines(scr)) > 0) { + FreezePiece(me); + Players[me].score.drops++; + Players[me].score.score++; + if ((linesCleared = ClearFullLines(me)) > 0) { if (game == GT_onePlayer) - if ((Players[scr].score.lines / 10) < - ((Players[scr].score.lines + linesCleared) / 10)) { + if ((Players[me].score.lines / 10) < + ((Players[me].score.lines + linesCleared) / 10)) { if ((Game.speed /= SPEEDINC) < SPEEDMINIMUM) Game.speed = SPEEDMINIMUM; SetITimer(Game.speed, SetITimer(0, 0)); - Players[scr].score.level++; + Players[me].score.level++; } //level up - Players[scr].score.score += linevalues[linesCleared]; - Players[scr].score.lines += linesCleared; - Players[scr].score.adds += linesCleared - (linesCleared < 4); + Players[me].score.score += linevalues[linesCleared - 1]; + Players[me].score.lines += linesCleared; + Players[me].score.adds += linesCleared - (linesCleared < 4); if (spied) - SendPacket(scr, NP_clear, 0, NULL); + SendPacket(me, NP_clear, 0, NULL); } if (game == GT_classicTwo && linesCleared > 1) { short junkLines; @@ -563,13 +646,19 @@ ExtFunc void OneGame(int scr) junkLines = linesCleared - (linesCleared < 4); data[0] = hton2(junkLines); - SendPacket(scr, NP_giveJunk, sizeof(data), data); - } + SendPacket(me, NP_giveJunk, sizeof(data), data); + Messagef("You sent %d lines", junkLines); + } //send junk to others } //new piece loop gameOver: SetITimer(0, 0); } +ExtFunc void CatchInt(int sig) +{ + siglongjmp(close_env, 1); +} + ExtFunc int main(int argc, char **argv) { char ch; @@ -582,19 +671,20 @@ ExtFunc int main(int argc, char **argv) int i; char *userName; - for (i = 0; i <= MAX_SCREENS; i++) + for (i = 0; i < MAX_SCREENS; i++) { Players[i].score.level = Players[i].spy = 1; + Players[i].boardWidth = 10; + Players[i].boardHeight = MAX_BOARD_HEIGHT; + Players[i].boardVisible = 20; + strcpy(Players[i].name, "???"); + } if (!(userName = getenv("LOGNAME")) || !userName[0]) if (!(userName = getenv("USER")) || !userName[0]) userName = "Anonymous"; strncpy(Players[0].name, userName, 16); //sizeof(Player.name) Players[0].name[16] = 0; - Players[0].boardWidth = 10; - Players[0].boardHeight = MAX_BOARD_HEIGHT; - Players[0].boardVisible = 20; - Players[0].spy = 1; Players[0].alive = 1; - } + } //set defaults // if (getopt(argc, argv, "f:") == 'f') // ReadConf(optarg); @@ -611,22 +701,27 @@ ExtFunc int main(int argc, char **argv) fatal("You can't use the -F option without the -r option"); // WriteConf(); - InitUtil(); - InitScreens(); + SRandom(time(0)); //randomize + if (sigsetjmp(close_env, 1)) + exit(0); + signal(SIGINT, CatchInt); //handle exit (^C) + InitScreens(); //setup screen + DrawTitle(); if (initConn) { game = GT_classicTwo; - Players[0].flags |= SCF_paused; - paused = SCF_paused; + spied = 1; InitiateConnection(hostStr, port); HandShake(); - OneGame(me); + checkPaused(); + OneGame(); } //client else { game = GT_onePlayer; - totalPlayers = 1; + Game.started = 2; + Game.maxplayers = 1; me = 1; memcpy(&Players[me], &Players[0], sizeof(Player)); - OneGame(me); + OneGame(); } //singleplay return 0; }