From e2bcb0a928cee4190ef0b86b06eb7ec083bf23f8 Mon Sep 17 00:00:00 2001 From: Florian Schulze Date: Sun, 27 Jun 2004 09:27:36 +0000 Subject: [PATCH] Added AI by Ricardo Cruz. This also adds mouse controls. --- AUTHORS | 3 + ChangeLog | 4 + VisualC6/jumpnbump.dsp | 2 +- globals.pre | 5 +- jumpnbump.6 | 11 +- main.c | 221 +++++++++++++++++++++++++++++++++++++++++ menu.c | 20 ++++ sdl/interrpt.c | 79 +++++++++++++++ 8 files changed, 342 insertions(+), 3 deletions(-) diff --git a/AUTHORS b/AUTHORS index f9e2d62..35ea1bb 100644 --- a/AUTHORS +++ b/AUTHORS @@ -56,3 +56,6 @@ Alessandro Gatti Ulrich Eckhardt Cleanup and small patches for enhanced networking. + +Ricardo Cruz + AI functions diff --git a/ChangeLog b/ChangeLog index 421d5da..e1c4617 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +27 Jun 2004 - 1.51 + - refactored code to make it a bit simpler + - Added AI by Ricardo Cruz + 30 Mar 2004 - 1.42 - added support for gzip and bzip2 packed levels. diff --git a/VisualC6/jumpnbump.dsp b/VisualC6/jumpnbump.dsp index de65599..c6450cb 100644 --- a/VisualC6/jumpnbump.dsp +++ b/VisualC6/jumpnbump.dsp @@ -43,7 +43,7 @@ RSC=rc.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SDL" /D "USE_NET" /D "ZLIB_SUPPORT" /D "BZLIB_SUPPORT" /YX /FD /c +# ADD CPP /nologo /MD /W3 /GX /O2 /I "../" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "USE_SDL" /D "USE_NET" /D "BZLIB_SUPPORT" /YX /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x407 /d "NDEBUG" diff --git a/globals.pre b/globals.pre index 469576e..f2346da 100644 --- a/globals.pre +++ b/globals.pre @@ -79,7 +79,7 @@ void tellServerPlayerMoved(int playerid, int movement_type, int newval); #define MOVEMENT_RIGHT 2 #define MOVEMENT_UP 3 -#define JNB_VERSION "1.42" +#define JNB_VERSION "1.51" #define JNB_WIDTH 400 #define JNB_HEIGHT 256 @@ -89,6 +89,8 @@ extern int screen_height; extern int screen_pitch; extern int scale_up; +extern int ai[JNB_MAX_PLAYERS]; + #ifndef USE_SDL #define KEY_PL1_LEFT 0xcb #define KEY_PL1_RIGHT 0xcd @@ -352,6 +354,7 @@ extern char last_keys[50]; int hook_keyb_handler(void); void remove_keyb_handler(void); int key_pressed(int key); +int addkey(unsigned int key); /* sound-linux.c */ #ifdef LINUX diff --git a/jumpnbump.6 b/jumpnbump.6 index 5acc604..a93092a 100644 --- a/jumpnbump.6 +++ b/jumpnbump.6 @@ -64,6 +64,15 @@ Left - 4 Right - 5 .br Jump - 8 +.IP "In the game" +Turn on/off computer play (AI) of bunny 1 - 1 +.br +Turn on/off computer play (AI) of bunny 2 - 2 +.br +Turn on/off computer play (AI) of bunny 3 - 3 +.br +Turn on/off computer play (AI) of bunny 4 - 4 +.br .SH SECRET CODES You can type these while in the game .br @@ -112,7 +121,7 @@ packed and are thus very large. .PP Chuck Mason , Jon Atkins , Philippe Brochard , Gürkan Sengün , -Florian Schulze and "timecop" are +Florian Schulze , Ricardo Cruz and "timecop" are the authors of jump'n'bump. .PP This program is a UNIX port of the old DOS game by brainchilddesign. diff --git a/main.c b/main.c index 6bb73e8..7cb4a09 100644 --- a/main.c +++ b/main.c @@ -65,6 +65,8 @@ int flip = 0; char pal[768]; char cur_pal[768]; +int ai[JNB_MAX_PLAYERS]; + unsigned int ban_map[17][22] = { {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0}, @@ -1432,6 +1434,11 @@ static int menu_loop(void) int c1, c2; int s1, s2; + for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) // reset player values + { + ai[c1] = 0; + } + while (1) { if (!is_net) @@ -1718,6 +1725,219 @@ static void player_action_right(int c1) } } +int map_tile(int pos_x, int pos_y) +{ +int tile; + +pos_x = pos_x >> 4; +pos_y = pos_y >> 4; + +if(pos_x < 0 || pos_x >= 17 || pos_y < 0 || pos_y >= 22) + return BAN_VOID; + +tile = ban_map[pos_y][pos_x]; +return tile; +} + +void cpu_move(void) +{ + int lm, rm, jm; + int i, j; + int cur_posx, cur_posy, tar_posx, tar_posy; + int players_distance; + player_t* target = NULL; + int nearest_distance = -1; + + for (i = 0; i < JNB_MAX_PLAYERS; i++) + { + nearest_distance = -1; + if(ai[i] && player[i].enabled) // this player is a computer + { // get nearest target + for (j = 0; j < JNB_MAX_PLAYERS; j++) + { + int deltax, deltay; + + if(i == j || !player[j].enabled) + continue; + + deltax = player[j].x - player[i].x; + deltay = player[j].y - player[i].y; + players_distance = deltax*deltax + deltay*deltay; + + if (players_distance < nearest_distance || nearest_distance == -1) + { + target = &player[j]; + nearest_distance = players_distance; + } + } + + if(target == NULL) + continue; + + cur_posx = player[i].x >> 16; + cur_posy = player[i].y >> 16; + tar_posx = target->x >> 16; + tar_posy = target->y >> 16; + + /** nearest player found, get him */ + /* here goes the artificial intelligence code */ + + /* X-axis movement */ + if(tar_posx > cur_posx) // if true target is on the right side + { // go after him + lm=0; + rm=1; + } + else // target on the left side + { + lm=1; + rm=0; + } + + if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 && + tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) + { + lm = !lm; + rm = !rm; + } + else if(tar_posx - cur_posx < 4+8 && tar_posx - cur_posx > -4) + { // makes the bunnies less "nervous" + lm=0; + lm=0; + } + + /* Y-axis movement */ + if(map_tile(cur_posx, cur_posy+16) != BAN_VOID && + ((i == 0 && key_pressed(KEY_PL1_JUMP)) || + (i == 1 && key_pressed(KEY_PL2_JUMP)) || + (i == 2 && key_pressed(KEY_PL3_JUMP)) || + (i == 3 && key_pressed(KEY_PL4_JUMP)))) + jm=0; // if we are on ground and jump key is being pressed, + //first we have to release it or else we won't be able to jump more than once + + else if(map_tile(cur_posx, cur_posy-8) != BAN_VOID && + map_tile(cur_posx, cur_posy-8) != BAN_WATER) + jm=0; // don't jump if there is something over it + + else if(map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_VOID && + map_tile(cur_posx-(lm*8)+(rm*16), cur_posy) != BAN_WATER && + cur_posx > 16 && cur_posx < 352-16-8) // obstacle, jump + jm=1; // if there is something on the way, jump over it + + else if(((i == 0 && key_pressed(KEY_PL1_JUMP)) || + (i == 1 && key_pressed(KEY_PL2_JUMP)) || + (i == 2 && key_pressed(KEY_PL3_JUMP)) || + (i == 3 && key_pressed(KEY_PL4_JUMP))) && + (map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_VOID && + map_tile(cur_posx-(lm*8)+(rm*16), cur_posy+8) != BAN_WATER)) + jm=1; // this makes it possible to jump over 2 tiles + + else if(cur_posy - tar_posy < 32 && cur_posy - tar_posy > 0 && + tar_posx - cur_posx < 32+8 && tar_posx - cur_posx > -32) // don't jump - running away + jm=0; + + else if(tar_posy <= cur_posy) // target on the upper side + jm=1; + else // target below + jm=0; + + /** Artificial intelligence done, now apply movements */ + if(lm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_LEFT; + else if(i == 1) + key = KEY_PL2_LEFT; + else if(i == 2) + key = KEY_PL3_LEFT; + else + key = KEY_PL4_LEFT; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_LEFT; + else if(i == 1) + key = KEY_PL2_LEFT; + else if(i == 2) + key = KEY_PL3_LEFT; + else + key = KEY_PL4_LEFT; + + key &= 0x7f; + addkey(key | 0x8000); + } + + if(rm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_RIGHT; + else if(i == 1) + key = KEY_PL2_RIGHT; + else if(i == 2) + key = KEY_PL3_RIGHT; + else + key = KEY_PL4_RIGHT; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_RIGHT; + else if(i == 1) + key = KEY_PL2_RIGHT; + else if(i == 2) + key = KEY_PL3_RIGHT; + else + key = KEY_PL4_RIGHT; + + key &= 0x7f; + addkey(key | 0x8000); + } + + if(jm) + { + SDLKey key; + if(i == 0) + key = KEY_PL1_JUMP; + else if(i == 1) + key = KEY_PL2_JUMP; + else if(i == 2) + key = KEY_PL3_JUMP; + else + key = KEY_PL4_JUMP; + + key &= 0x7f; + addkey(key); + } + else + { + SDLKey key; + if(i == 0) + key = KEY_PL1_JUMP; + else if(i == 1) + key = KEY_PL2_JUMP; + else if(i == 2) + key = KEY_PL3_JUMP; + else + key = KEY_PL4_JUMP; + + key &= 0x7f; + addkey(key | 0x8000); + } + } + } +} + #define GET_BAN_MAP_IN_WATER(s1, s2) (GET_BAN_MAP_XY((s1), ((s2) + 7)) == BAN_VOID || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 7)) == BAN_VOID) && (GET_BAN_MAP_XY((s1), ((s2) + 8)) == BAN_WATER || GET_BAN_MAP_XY(((s1) + 15), ((s2) + 8)) == BAN_WATER) @@ -1727,6 +1947,7 @@ void steer_players(void) int c1, c2; int s1 = 0, s2 = 0; + cpu_move(); update_player_actions(); for (c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) { diff --git a/menu.c b/menu.c index 2f53113..563c25e 100644 --- a/menu.c +++ b/menu.c @@ -77,6 +77,23 @@ int menu(void) if (menu_init() != 0) return 1; + /* After a game, we have to release the keys, cause AI player + can still be using them */ + addkey((KEY_PL1_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL2_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL3_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL4_LEFT & 0x7f) | 0x8000); + + addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000); + + addkey((KEY_PL1_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL2_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + addkey((KEY_PL4_JUMP & 0x7f) | 0x8000); + mod_vol = 0; mod_fade_direction = 1; dj_ready_mod(MOD_MENU); @@ -106,6 +123,9 @@ int menu(void) dj_mix(); + for(c1 = 0; c1 < JNB_MAX_PLAYERS; c1++) // set AI to false + ai[c1] = 0; + while (update_count) { if (key_pressed(1) == 1 && esc_pressed == 0) { diff --git a/sdl/interrpt.c b/sdl/interrpt.c index 5f72277..91a27ab 100644 --- a/sdl/interrpt.c +++ b/sdl/interrpt.c @@ -310,6 +310,49 @@ int intr_sysupdate() while (SDL_PollEvent(&e)) { switch (e.type) { case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if(e.button.state == SDL_PRESSED && + ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) || + (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) || + (e.button.button == SDL_BUTTON_LEFT && e.button.button == SDL_BUTTON_RIGHT) || + e.button.button == SDL_BUTTON_MIDDLE)) + { + addkey(KEY_PL3_JUMP & 0x7f); + } + else if(e.button.state == SDL_RELEASED && + ((key_pressed(KEY_PL3_LEFT) && e.button.button == SDL_BUTTON_RIGHT) || + (key_pressed(KEY_PL3_RIGHT) && e.button.button == SDL_BUTTON_LEFT) || + e.button.button == SDL_BUTTON_MIDDLE)) + { + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + } + + if(e.button.button == SDL_BUTTON_LEFT) + { + SDLKey sym = KEY_PL3_LEFT; + sym &= 0x7f; + if(e.button.state == SDL_RELEASED) + { + if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_RIGHT))) + addkey(KEY_PL3_RIGHT & 0x7f); + else + sym |= 0x8000; + } + addkey(sym); + } + else if(e.button.button == SDL_BUTTON_RIGHT) + { + SDLKey sym = KEY_PL3_RIGHT; + sym &= 0x7f; + if (e.button.state == SDL_RELEASED) + { + if(key_pressed(KEY_PL3_JUMP) && (SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(SDL_BUTTON_LEFT))) + addkey(KEY_PL3_LEFT & 0x7f); + else + sym |= 0x8000; + } + addkey(sym); + } break; case SDL_KEYDOWN: case SDL_KEYUP: @@ -325,6 +368,42 @@ int intr_sysupdate() fs_toggle(); } break; + case SDLK_1: + if (e.type == SDL_KEYUP) + ai[0] = !ai[0]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL1_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL1_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL1_JUMP & 0x7f) | 0x8000); + break; + case SDLK_2: + if (e.type == SDL_KEYUP) + ai[1] = !ai[1]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL2_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL2_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL2_JUMP & 0x7f) | 0x8000); + break; + case SDLK_3: + if (e.type == SDL_KEYUP) + ai[2] = !ai[2]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL3_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL3_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL3_JUMP & 0x7f) | 0x8000); + break; + case SDLK_4: + if (e.type == SDL_KEYUP) + ai[3] = !ai[3]; + + /* Release keys, otherwise it will continue moving that way */ + addkey((KEY_PL4_LEFT & 0x7f) | 0x8000); + addkey((KEY_PL4_RIGHT & 0x7f) | 0x8000); + addkey((KEY_PL4_JUMP & 0x7f) | 0x8000); + break; case SDLK_ESCAPE: if (e.type == SDL_KEYUP) addkey(1 | 0x8000); -- 2.39.2