Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class MPBot {
- public static final int NO_INPUT = 0x00;
- public static final int A = 0x01;
- public static final int B = 0x02;
- public static final int SELECT = 0x04;
- public static final int START = 0x08;
- public static final int RIGHT = 0x10;
- public static final int LEFT = 0x20;
- public static final int UP = 0x40;
- public static final int DOWN = 0x80;
- private static final int HARD_RESET = 0x800;
- private static final String gameName;
- private static PrintWriter writer;
- private static PrintWriter particallyManips;
- // Graph is only built right now to waste 10 steps, so more would need to be
- // added to make use of >= 204 frames.
- // Also more intros would need to be spelled out.
- private static final int MAX_COST;
- private static final int MIN_CONSISTENCY = 52; // x/60
- private static final Location dest1 = new Location(17, 11);
- private static final Location dest2 = new Location(17, 11);
- private static final Location dest3 = new Location(28, 5);
- private static final Location dest4 = new Location(25, 9);
- private static final Location dest5 = new Location(25, 9);
- private static final Location dest6 = new Location(3, 2);
- private static final Location dest7 = new Location(5, 5);
- private static final Location dest8 = new Location(21, 17);
- private static final Location dest9 = new Location(12, 31);
- private static PalStrat pal = new PalStrat("_pal", 0, new Integer[] { RedBlueAddr.biosReadKeypadAddr }, new Integer[] { LEFT }, new Integer[] { 1 });
- private static PalStrat nopal = new PalStrat("_nopal", 0, new Integer[] { RedBlueAddr.biosReadKeypadAddr }, new Integer[] { NO_INPUT }, new Integer[] { 1 });
- private static PalStrat abss = new PalStrat("_nopal(ab)", 0, new Integer[] { RedBlueAddr.biosReadKeypadAddr, RedBlueAddr.initAddr }, new Integer[] { A, A }, new Integer[] { 0, 0 });
- private static PalStrat holdpal = new PalStrat("_pal(hold)", 0, new Integer[] { RedBlueAddr.biosReadKeypadAddr, RedBlueAddr.initAddr }, new Integer[] { LEFT, LEFT }, new Integer[] { 0, 0 });
- private static IntroSequence sequence;
- private static PalStrat palstrat = holdpal;
- private static int successes = 0;
- private static HashMap<OverworldStateMP, ByteBuffer[]> saveMap = new HashMap<OverworldStateMP, ByteBuffer[]>();
- private static ArrayList<Long> seenStates = new ArrayList<Long>();
- static {
- MAX_COST = 2 * 7 + 34 * 3;
- gameName = "red";
- }
- // Sort tiles by starting cost (lower starting cost takes priority),
- // then by starting distance from grass (longer distance takes priority).
- //
- // The idea being that if you get to a state that's already been reached, it
- // has been from a state that has wasted
- // fewer frames to get to that point.
- static class SaveTileComparator implements Comparator<SaveTile> {
- @Override
- public int compare(SaveTile o1, SaveTile o2) {
- if (o1.getStartCost() != o2.getStartCost()) {
- return o1.getTrueStartCost() - o2.getTrueStartCost();
- } else {
- return o2.getOwPos().getMinStepsToGrass() - o1.getOwPos().getMinStepsToGrass();
- }
- }
- }
- public static void main(String[] args) throws IOException, InterruptedException {
- // Make folder if necessary
- if (!new File("logs").exists()) {
- new File("logs").mkdir();
- }
- if (!new File("roms").exists()) {
- new File("roms").mkdir();
- System.err.println("I need ROMs to simulate!");
- System.exit(0);
- }
- if (!new File("roms/poke" + gameName + ".gbc").exists()) {
- System.err.println("Could not find poke" + gameName + ".gbc in roms directory!");
- System.exit(0);
- }
- writer = new PrintWriter(new File(gameName + "_moon_paths.txt"));
- particallyManips = new PrintWriter(new File(gameName + "_partially_paths.txt"));
- sequence = new IntroSequence(palstrat, gfSkip, nido0, title0, cont, cont);
- System.out.println("Number of intro sequences: " + 1);
- long startTime = System.currentTimeMillis();
- pw1 = initTiles(pw1, RBMap.MT_MOON_1.getPokeworldOffsetX(), RBMap.MT_MOON_1.getPokeworldOffsetY(), RBMap.MT_MOON_1.getWidthInTiles(), RBMap.MT_MOON_1.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_1, dest1));
- pw2 = initTiles(pw2, RBMap.MT_MOON_2.getPokeworldOffsetX(), RBMap.MT_MOON_2.getPokeworldOffsetY(), RBMap.MT_MOON_2.getWidthInTiles(), RBMap.MT_MOON_2.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_2, dest2));
- pw3 = initTiles(pw3, RBMap.MT_MOON_3.getPokeworldOffsetX(), RBMap.MT_MOON_3.getPokeworldOffsetY(), RBMap.MT_MOON_3.getWidthInTiles(), RBMap.MT_MOON_3.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_3, dest3));
- pw4 = initTiles(pw4, RBMap.MT_MOON_3.getPokeworldOffsetX(), RBMap.MT_MOON_3.getPokeworldOffsetY(), RBMap.MT_MOON_3.getWidthInTiles(), RBMap.MT_MOON_3.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_3, dest4));
- pw5 = initTiles(pw5, RBMap.MT_MOON_2.getPokeworldOffsetX(), RBMap.MT_MOON_2.getPokeworldOffsetY(), RBMap.MT_MOON_2.getWidthInTiles(), RBMap.MT_MOON_2.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_2, dest5));
- pw6 = initTiles(pw6, RBMap.MT_MOON_1.getPokeworldOffsetX(), RBMap.MT_MOON_1.getPokeworldOffsetY(), RBMap.MT_MOON_1.getWidthInTiles(), RBMap.MT_MOON_1.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_1, dest6));
- pw7 = initTiles(pw7, RBMap.MT_MOON_1.getPokeworldOffsetX(), RBMap.MT_MOON_1.getPokeworldOffsetY(), RBMap.MT_MOON_1.getWidthInTiles(), RBMap.MT_MOON_1.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_1, dest7));
- pw8 = initTiles(pw8, RBMap.MT_MOON_2.getPokeworldOffsetX(), RBMap.MT_MOON_2.getPokeworldOffsetY(), RBMap.MT_MOON_2.getWidthInTiles(), RBMap.MT_MOON_2.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_2, dest8));
- pw9 = initTiles(pw9, RBMap.MT_MOON_3.getPokeworldOffsetX(), RBMap.MT_MOON_3.getPokeworldOffsetY(), RBMap.MT_MOON_3.getWidthInTiles(), RBMap.MT_MOON_3.getHeightInTiles(), false, new RBMapDestination(RBMap.MT_MOON_3, dest9));
- // Connect the stages
- pw1[17][10].getEdge(OverworldAction.DOWN).setNextPos(pw2[25][9]);
- pw1[16][11].getEdge(OverworldAction.RIGHT).setNextPos(pw2[25][9]);
- pw1[17][12].getEdge(OverworldAction.UP).setNextPos(pw2[25][9]);
- pw2[17][10].getEdge(OverworldAction.DOWN).setNextPos(pw3[25][9]);
- pw2[18][11].getEdge(OverworldAction.LEFT).setNextPos(pw3[25][9]);
- pw2[16][11].getEdge(OverworldAction.RIGHT).setNextPos(pw3[25][9]);
- pw3[27][5].getEdge(OverworldAction.RIGHT).setNextPos(pw4[28][5]);
- pw4[26][9].getEdge(OverworldAction.LEFT).setNextPos(pw5[17][11]);
- pw4[25][10].getEdge(OverworldAction.UP).setNextPos(pw5[17][11]);
- pw4[24][9].getEdge(OverworldAction.RIGHT).setNextPos(pw5[17][11]);
- pw4[25][8].getEdge(OverworldAction.DOWN).setNextPos(pw5[17][11]);
- pw5[25][10].getEdge(OverworldAction.UP).setNextPos(pw6[17][11]);
- pw5[24][9].getEdge(OverworldAction.LEFT).setNextPos(pw6[17][11]);
- pw5[25][8].getEdge(OverworldAction.DOWN).setNextPos(pw6[17][11]);
- pw6[3][2].getEdge(OverworldAction.DOWN).setNextPos(pw7[3][3]);
- pw6[3][2].getEdge(OverworldAction.RIGHT).setNextPos(pw7[4][2]);
- pw7[5][4].getEdge(OverworldAction.DOWN).setNextPos(pw8[5][5]);
- pw7[4][5].getEdge(OverworldAction.RIGHT).setNextPos(pw8[5][5]);
- pw7[6][5].getEdge(OverworldAction.LEFT).setNextPos(pw8[5][5]);
- pw8[20][17].getEdge(OverworldAction.RIGHT).setNextPos(pw9[21][17]);
- pw8[21][16].getEdge(OverworldAction.DOWN).setNextPos(pw9[21][17]);
- saveTiles.add(new SaveTile(pw1[24][7], 0, false));
- long endTime = System.currentTimeMillis();
- System.out.printf("Generic edge generation time: %d ms\n", endTime - startTime);
- for (SaveTile saveTile : saveTiles) {
- OverworldTile savePos = saveTile.getOwPos();
- Gb.loadGambatte(1);
- gb = new Gb(0, false);
- gb.startEmulator("roms/poke" + gameName + ".gbc");
- mem = new GBMemory(gb);
- wrap = new GBWrapper(gb, mem);
- OverworldStateMP owState = new OverworldStateMP(savePos.toString() + " - " + sequence.toString() + ":", saveTile.getOwPos(), (byte)1, true, new boolean[2], (byte)0, (byte)gb.getDivState(), (byte)mem.getHRA(), (byte)mem.getHRS(), saveTile.isViridianNpc(), (byte)mem.getTurnFrameStatus(), mem.getNPCTimers(), (short)0, (short)0);
- overworldSearch(owState);
- }
- writer.close();
- }
- private static boolean isNull(ByteBuffer[] saves) {
- for(ByteBuffer save : saves) {
- if(save != null) {
- return false;
- }
- }
- return true;
- }
- private static int i = 0;
- private static void overworldSearch(OverworldStateMP ow) {
- i++;
- if(i % 80 == 0) {
- ArrayList<OverworldStateMP> sortedList = new ArrayList<>(saveMap.keySet());
- Collections.sort(sortedList);
- for(int i = 0; i < 30; i++) {
- saveMap.remove(sortedList.get(i));
- }
- }
- if(!seenStates.add(ow.getFfefUniqId())) {
- return;
- }
- if (ow.getWastedFrames() > MAX_COST) {
- return;
- }
- if (ow.getMap() == 33 && ow.getX() == 33 && ow.getY() == 11 && ow.getWastedFrames() + 34 > MAX_COST) {
- return;
- }
- ByteBuffer[] saves = saveMap.get(ow);
- if(saves == null) {
- saves = new ByteBuffer[60];
- }
- for (OverworldEdge edge : ow.getPos().getEdgeList()) {
- OverworldAction edgeAction = edge.getAction();
- if (ow.getMap() == 1 && ow.getX() == 47 - 30 && edgeAction == OverworldAction.RIGHT && ow.isViridianNpc()) {
- continue;
- }
- if (ow.aPressCounter() > 0 && (edgeAction == OverworldAction.A || edgeAction == OverworldAction.START_B || edgeAction == OverworldAction.S_A_B_S || edgeAction == OverworldAction.S_A_B_A_B_S)) {
- continue;
- }
- if (!ow.canPressStart() && (edgeAction == OverworldAction.START_B || edgeAction == OverworldAction.S_A_B_S || edgeAction == OverworldAction.S_A_B_A_B_S)) {
- continue;
- }
- int edgeCost = edge.getCost();
- if (ow.getWastedFrames() + edgeCost > MAX_COST) {
- continue;
- }
- OverworldStateMP newState;
- int owFrames = ow.getOverworldFrames() + edge.getFrames();
- ByteBuffer[] newsaves = new ByteBuffer[60];
- for(int i = 0; i < 60; i++) {
- newsaves[i] = saves[i];
- }
- switch (edgeAction) {
- case LEFT:
- case UP:
- case RIGHT:
- case DOWN:
- newState = checkIGT0(newsaves, ow, edge, Math.max(0, ow.aPressCounter() - 1), true);
- if (successes < MIN_CONSISTENCY) {
- break;
- }
- if (mem.getX() == dest9.x && mem.getY() == dest9.y && mem.getMap() == 61) {
- writer.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- writer.flush();
- } else {
- particallyManips.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- particallyManips.flush();
- saveMap.put(newState, newsaves);
- overworldSearch(newState);
- }
- break;
- case A:
- newState = checkIGT0(newsaves, ow, edge, 2, true);
- if (successes < MIN_CONSISTENCY) {
- break;
- }
- if (mem.getX() == dest9.x && mem.getY() == dest9.y && mem.getMap() == 61) {
- writer.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- writer.flush();
- } else {
- particallyManips.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- particallyManips.flush();
- saveMap.put(newState, newsaves);
- overworldSearch(newState);
- }
- break;
- case START_B:
- newState = checkIGT0(newsaves, ow, edge, 1, true);
- if (successes < MIN_CONSISTENCY) {
- break;
- }
- if (mem.getX() == dest9.x && mem.getY() == dest9.y && mem.getMap() == 61) {
- writer.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- writer.flush();
- } else {
- particallyManips.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- particallyManips.flush();
- saveMap.put(newState, newsaves);
- overworldSearch(newState);
- }
- break;
- case S_A_B_S:
- newState = checkIGT0(newsaves, ow, edge, 1, false);
- if (successes < MIN_CONSISTENCY) {
- break;
- }
- if (mem.getX() == dest9.x && mem.getY() == dest9.y && mem.getMap() == 61) {
- writer.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- writer.flush();
- } else {
- particallyManips.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- particallyManips.flush();
- saveMap.put(newState, newsaves);
- overworldSearch(newState);
- }
- break;
- case S_A_B_A_B_S:
- newState = checkIGT0(newsaves, ow, edge, 1, false);
- if (successes < MIN_CONSISTENCY) {
- break;
- }
- if (mem.getX() == dest9.x && mem.getY() == dest9.y && mem.getMap() == 61) {
- writer.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- writer.flush();
- } else {
- particallyManips.println(ow.toString() + " " + edgeAction.logStr() + ", cost: " + (ow.getWastedFrames() + edgeCost) + ", owFrames: " + (owFrames) + " - " + successes + "/60");
- particallyManips.flush();
- saveMap.put(newState, newsaves);
- overworldSearch(newState);
- }
- break;
- default:
- break;
- }
- }
- }
- private static OverworldStateMP checkIGT0(ByteBuffer[] saves, OverworldStateMP ow, OverworldEdge edge, int aPress, boolean startPress) {
- int successes = 60;
- ByteBuffer save = null;
- boolean areSavesNull = isNull(saves);
- if(areSavesNull) {
- gb.step(HARD_RESET);
- palstrat.execute(wrap);
- gfSkip.execute(wrap);
- nido0.execute(wrap);
- title0.execute(wrap);
- wrap.advanceToAddress(RedBlueAddr.igtInjectAddr);
- save = gb.saveState();
- }
- for (int i = 0; i <= 59; i++) {
- save = !areSavesNull ? saves[i] : save;
- if(save == null) {
- successes--;
- continue;
- }
- wrap.loadState(save);
- if(areSavesNull) {
- gb.writeMemory(0xDA45, i);
- cont.execute(wrap);
- cont.execute(wrap);
- wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr);
- }
- if (!execute(ow, edge, i)) {
- successes--;
- saves[i] = null;
- continue;
- }
- int res = wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr, RedBlueAddr.playCryAddr);
- if(res == RedBlueAddr.joypadOverworldAddr) {
- saves[i] = gb.saveState();
- }
- }
- boolean[] itemsPickedUp = ow.getItemsPickedUp();
- int itemIdx = ow.getItemIdx();
- if(timeToPickUpItem(ow.getMap(), ow.getX(), ow.getY(), itemsPickedUp)) {
- itemsPickedUp[itemIdx++] = true;
- }
- OverworldStateMP newState = new OverworldStateMP(ow.toString() + " " + edge.getAction().logStr(), edge.getNextPos(), (byte)aPress, startPress, itemsPickedUp, (byte)itemIdx, (byte)gb.getDivState(), (byte)mem.getHRA(), (byte)mem.getHRS(), ow.isViridianNpc(), (byte)mem.getTurnFrameStatus(), mem.getNPCTimers(), (short)(ow.getWastedFrames() + edge.getCost()), (short)(ow.getOverworldFrames() + (byte)edge.getFrames()));
- MPBot.successes = successes;
- return newState;
- }
- private static boolean execute(OverworldStateMP ow, OverworldEdge edge, int i) {
- OverworldAction owAction = edge.getAction();
- int res;
- // System.out.print(owAction.logStr());
- switch (owAction) {
- case LEFT:
- case UP:
- case RIGHT:
- case DOWN:
- int input = 16 * (int) (Math.pow(2.0, (owAction.ordinal())));
- // Execute the action
- wrap.injectRBInput(input);
- wrap.advanceWithJoypadToAddress(input, RedBlueAddr.joypadOverworldAddr + 1);
- if (travellingToWarp(edge.getNextPos().getMap(), edge.getNextPos().getX(), edge.getNextPos().getY())) {
- wrap.advanceWithJoypadToAddress(input, RedBlueAddr.enterMapAddr);
- wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr);
- } else {
- int result = wrap.advanceWithJoypadToAddress(input, RedBlueAddr.joypadOverworldAddr, RedBlueAddr.newBattleAddr, RedBlueAddr.manualTextScrollAddr);
- if (result == RedBlueAddr.manualTextScrollAddr) {
- System.out.println("TEXTBOX HIT AT " + mem.getX() + " " + mem.getY());
- return false;
- }
- // Did we turnframe or hit an
- // ignored input frame after
- // a
- // warp?
- while (mem.getX() != edge.getNextPos().getX() || mem.getY() != edge.getNextPos().getY()) {
- if (result == RedBlueAddr.newBattleAddr) {
- // Check for garbage
- int result2 = wrap.advanceWithJoypadToAddress(input, RedBlueAddr.encounterTestAddr, RedBlueAddr.joypadOverworldAddr);
- if (result2 == RedBlueAddr.encounterTestAddr) {
- // Yes we can. What's up
- // on this tile?
- int hra = mem.getHRA();
- // logLN("hrandom add was "+hra);
- if (hra < 10) {
- return false;
- }
- }
- }
- // Do that input again
- wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr);
- wrap.injectRBInput(input);
- wrap.advanceWithJoypadToAddress(input, RedBlueAddr.joypadOverworldAddr + 1);
- result = wrap.advanceWithJoypadToAddress(input, RedBlueAddr.newBattleAddr, RedBlueAddr.joypadOverworldAddr);
- }
- // Can we get an encounter now?
- int result2 = wrap.advanceToAddress(RedBlueAddr.encounterTestAddr, RedBlueAddr.joypadOverworldAddr, RedBlueAddr.manualTextScrollAddr);
- if (result2 == RedBlueAddr.manualTextScrollAddr) {
- System.out.println("TEXTBOX HIT AT " + mem.getX() + " " + mem.getY());
- return false;
- }
- if (result2 == RedBlueAddr.encounterTestAddr) {
- int hra = mem.getHRA();
- if (hra < 10) {
- return false;
- }
- wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr);
- if (timeToPickUpItem(mem.getMap(), mem.getX(), mem.getY(), ow.getItemsPickedUp())) {
- // Pick it up
- wrap.injectRBInput(A);
- wrap.advanceWithJoypadToAddress(A, RedBlueAddr.textJingleCommandAddr);
- wrap.advanceToAddress(RedBlueAddr.joypadOverworldAddr);
- }
- }
- }
- return true;
- case A:
- wrap.injectRBInput(A);
- wrap.advanceFrame(A);
- res = wrap.advanceWithJoypadToAddress(A, RedBlueAddr.joypadOverworldAddr, RedBlueAddr.printLetterDelayAddr, RedBlueAddr.manualTextScrollAddr);
- if (res == RedBlueAddr.manualTextScrollAddr) {
- System.out.println("TEXTBOX HIT AT " + mem.getX() + " " + mem.getY());
- return false;
- }
- if (res == RedBlueAddr.joypadOverworldAddr) {
- return true;
- } else {
- return false;
- }
- case START_B:
- wrap.injectRBInput(START);
- wrap.advanceFrame(START);
- wrap.advanceWithJoypadToAddress(START, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(B);
- wrap.advanceFrame(B);
- wrap.advanceWithJoypadToAddress(B, RedBlueAddr.joypadOverworldAddr);
- return true;
- case S_A_B_S:
- wrap.injectRBInput(START);
- wrap.advanceFrame(START);
- wrap.advanceToAddress(RedBlueAddr.joypadAddr);
- wrap.injectRBInput(A);
- wrap.advanceFrame(A);
- wrap.advanceWithJoypadToAddress(A, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(B);
- wrap.advanceFrame(B);
- wrap.advanceWithJoypadToAddress(B, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(START);
- wrap.advanceFrame(START);
- wrap.advanceWithJoypadToAddress(START, RedBlueAddr.joypadOverworldAddr);
- return true;
- case S_A_B_A_B_S:
- wrap.injectRBInput(START);
- wrap.advanceFrame(START);
- wrap.advanceWithJoypadToAddress(START, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(A);
- wrap.advanceFrame(A);
- wrap.advanceWithJoypadToAddress(A, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(B);
- wrap.advanceFrame(B);
- wrap.advanceWithJoypadToAddress(B, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(A);
- wrap.advanceFrame(A);
- wrap.advanceWithJoypadToAddress(A, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(B);
- wrap.advanceFrame(B);
- wrap.advanceWithJoypadToAddress(B, RedBlueAddr.joypadAddr);
- wrap.injectRBInput(START);
- wrap.advanceFrame(START);
- wrap.advanceWithJoypadToAddress(START, RedBlueAddr.joypadOverworldAddr);
- return true;
- default:
- return false;
- }
- }
- private static List<SaveTile> saveTiles = new ArrayList<>();
- private static OverworldTile[][] pw1 = new OverworldTile[RBMap.MT_MOON_1.getWidthInTiles() + 1][RBMap.MT_MOON_1.getHeightInTiles() + 1];
- private static OverworldTile[][] pw2 = new OverworldTile[RBMap.MT_MOON_2.getWidthInTiles() + 1][RBMap.MT_MOON_2.getHeightInTiles() + 1];
- private static OverworldTile[][] pw3 = new OverworldTile[RBMap.MT_MOON_3.getWidthInTiles() + 1][RBMap.MT_MOON_3.getHeightInTiles() + 1];
- private static OverworldTile[][] pw4 = new OverworldTile[RBMap.MT_MOON_3.getWidthInTiles() + 1][RBMap.MT_MOON_3.getHeightInTiles() + 1];
- private static OverworldTile[][] pw5 = new OverworldTile[RBMap.MT_MOON_2.getWidthInTiles() + 1][RBMap.MT_MOON_2.getHeightInTiles() + 1];
- private static OverworldTile[][] pw6 = new OverworldTile[RBMap.MT_MOON_1.getWidthInTiles() + 1][RBMap.MT_MOON_1.getHeightInTiles() + 1];
- private static OverworldTile[][] pw7 = new OverworldTile[RBMap.MT_MOON_1.getWidthInTiles() + 1][RBMap.MT_MOON_1.getHeightInTiles() + 1];
- private static OverworldTile[][] pw8 = new OverworldTile[RBMap.MT_MOON_2.getWidthInTiles() + 1][RBMap.MT_MOON_2.getHeightInTiles() + 1];
- private static OverworldTile[][] pw9 = new OverworldTile[RBMap.MT_MOON_3.getWidthInTiles() + 1][RBMap.MT_MOON_3.getHeightInTiles() + 1];
- private static Gb gb;
- private static GBWrapper wrap;
- private static GBMemory mem;
- private static OverworldTile[][] initTiles(OverworldTile[][] pw, int PW_START_X, int PW_START_Y, int PW_WIDTH, int PW_HEIGHT, boolean onBike, RBMapDestination... destinations) {
- int numFramesPerStep = 17;
- HashMap<RBMap, RBMapDestination> dests = new HashMap<RBMap, RBMapDestination>();
- HashMap<OverworldTile, List<Node>> paths = new HashMap<OverworldTile, List<Node>>();
- for (RBMapDestination dest : destinations) {
- dests.put(dest.getMap(), dest);
- }
- for (int i = 0; i <= PW_WIDTH; i++) {
- for (int j = 0; j <= PW_HEIGHT; j++) {
- int pwX = i + PW_START_X;
- int pwY = j + PW_START_Y;
- RBMap map = RBMap.getMapByPosition(pwX, pwY);
- int tileX = pwX - map.getPokeworldOffsetX();
- int tileY = pwY - map.getPokeworldOffsetY();
- if (map.getOverworldTile(tileX, tileY) != null) {
- pw[i][j] = new OverworldTile(map.getId(), tileX, tileY);
- }
- }
- }
- for (int i = 0; i <= PW_WIDTH; i++) {
- for (int j = 0; j <= PW_HEIGHT; j++) {
- if (pw[i][j] == null) {
- // tile is solid, don't want to waste calculating paths
- continue;
- }
- RBMap map = RBMap.getMapByID(pw[i][j].getMap());
- RBMapDestination dest = dests.get(map);
- if (dest == null) {
- dest = new RBMapDestination(map);
- dests.put(map, dest);
- }
- OverworldTilePath path = new OverworldTilePath(pw[i][j], dest);
- if (path.getShortestPath() == null) {
- // could not find a path to the destination
- continue;
- }
- List<Node> shortestPath = path.getShortestPath();
- pw[i][j].setMinStepsToGrass(shortestPath.size());
- paths.put(pw[i][j], shortestPath);
- }
- }
- for (int i = 0; i <= PW_WIDTH; i++) {
- for (int j = 0; j <= PW_HEIGHT; j++) {
- if (pw[i][j] == null) {
- // tile is solid, don't want to waste calculating paths
- continue;
- }
- RBMap map = RBMap.getMapByID(pw[i][j].getMap());
- RBMapDestination dest = dests.get(map);
- List<Node> path = paths.get(pw[i][j]);
- if (path == null) {
- continue;
- }
- if (dest.getMode() == RBMapDestination.WEST_CONNECTION && path.get(path.size() - 1).getPosition().x == 0) {
- RBMap destMap = map.getWestConnection();
- int tileX = destMap.getWidthInTiles() - 1;
- int tileY = path.get(path.size() - 1).getPosition().y + map.getPokeworldOffsetY() - destMap.getPokeworldOffsetY();
- pw[i][j].setMinStepsToGrass(pw[i][j].getMinStepsToGrass() + destMap.getOverworldTile(tileX, tileY).getMinStepsToGrass());
- }
- if (dest.getMode() == RBMapDestination.EAST_CONNECTION && path.get(path.size() - 1).getPosition().x == map.getWidthInTiles() - 1) {
- RBMap destMap = map.getWestConnection();
- int tileX = destMap.getWidthInTiles() + 1;
- int tileY = path.get(path.size() - 1).getPosition().y + map.getPokeworldOffsetY() - destMap.getPokeworldOffsetY();
- pw[i][j].setMinStepsToGrass(pw[i][j].getMinStepsToGrass() + destMap.getOverworldTile(tileX, tileY).getMinStepsToGrass());
- }
- if (dest.getMode() == RBMapDestination.SOUTH_CONNECTION && path.get(path.size() - 1).getPosition().y == map.getHeightInTiles() - 1) {
- RBMap destMap = map.getWestConnection();
- int tileX = path.get(path.size() - 1).getPosition().x + map.getPokeworldOffsetX() - destMap.getPokeworldOffsetX();
- int tileY = destMap.getHeightInTiles() + 1;
- pw[i][j].setMinStepsToGrass(pw[i][j].getMinStepsToGrass() + destMap.getOverworldTile(tileX, tileY).getMinStepsToGrass());
- }
- if (dest.getMode() == RBMapDestination.NORTH_CONNECTION && path.get(path.size() - 1).getPosition().y == 0) {
- RBMap destMap = map.getWestConnection();
- int tileX = path.get(path.size() - 1).getPosition().x + map.getPokeworldOffsetX() - destMap.getPokeworldOffsetX();
- int tileY = destMap.getHeightInTiles() - 1;
- pw[i][j].setMinStepsToGrass(pw[i][j].getMinStepsToGrass() + destMap.getOverworldTile(tileX, tileY).getMinStepsToGrass());
- }
- }
- }
- for (int i = 0; i <= PW_WIDTH; i++) {
- for (int j = 0; j <= PW_HEIGHT; j++) {
- if (pw[i][j] == null) {
- // tile is solid, don't want to waste calculating edges
- continue;
- }
- RBMap map = RBMap.getMapByID(pw[i][j].getMap());
- RBMapTile tile = map.getTile(pw[i][j].getX(), pw[i][j].getY());
- if (tile.canMoveLeft()) {
- if (i != 0) {
- OverworldTile destTile = pw[i - 1][j];
- if (destTile != null) {
- int cost = Math.abs(numFramesPerStep * (destTile.getMinStepsToGrass() - pw[i][j].getMinStepsToGrass() + 1));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.LEFT, cost, numFramesPerStep, destTile));
- }
- }
- }
- if (tile.canMoveRight()) {
- if (i != PW_WIDTH) {
- OverworldTile destTile = pw[i + 1][j];
- if (destTile != null) {
- int cost = Math.abs(numFramesPerStep * (destTile.getMinStepsToGrass() - pw[i][j].getMinStepsToGrass() + 1));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.RIGHT, cost, numFramesPerStep, destTile));
- }
- }
- }
- if (tile.canMoveUp()) {
- if (j != 0) {
- OverworldTile destTile = pw[i][j - 1];
- if (destTile != null) {
- int cost = Math.abs(numFramesPerStep * (destTile.getMinStepsToGrass() - pw[i][j].getMinStepsToGrass() + 1));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.UP, cost, numFramesPerStep, destTile));
- }
- }
- }
- if (tile.canMoveDown()) {
- if (j != PW_HEIGHT) {
- OverworldTile destTile = pw[i][j + 1];
- if (destTile != null) {
- int cost = Math.abs(numFramesPerStep * (destTile.getMinStepsToGrass() - pw[i][j].getMinStepsToGrass() + 1));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.DOWN, cost, numFramesPerStep, destTile));
- }
- }
- }
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.A, 2, 2, pw[i][j]));
- int sbcost = 52;
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.START_B, sbcost, sbcost, pw[i][j]));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.S_A_B_S, sbcost + 30, sbcost + 30, pw[i][j]));
- pw[i][j].addEdge(new OverworldEdge(OverworldAction.S_A_B_A_B_S, sbcost + 60, sbcost + 60, pw[i][j]));
- Collections.sort(pw[i][j].getEdgeList());
- }
- }
- return pw;
- }
- public static Position getDestination(GBMemory mem, int input) {
- if (input == LEFT) {
- return new Position(mem.getMap(), mem.getX() - 1, mem.getY());
- } else if (input == RIGHT) {
- return new Position(mem.getMap(), mem.getX() + 1, mem.getY());
- } else if (input == UP) {
- return new Position(mem.getMap(), mem.getX(), mem.getY() - 1);
- } else if (input == DOWN) {
- return new Position(mem.getMap(), mem.getX(), mem.getY() + 1);
- } else {
- return new Position(mem.getMap(), mem.getX(), mem.getY());
- }
- }
- public static boolean timeToPickUpItem(int map, int x, int y, boolean[] pickedUpItems) {
- if (map == 61) {
- if (!pickedUpItems[0] && x == 28 && y == 5) {
- return true;
- }
- }
- if (map == 59) {
- if (!pickedUpItems[1] && x == 3 && y == 2) {
- return true;
- }
- }
- return false;
- }
- static class Strat {
- String name;
- int cost;
- Integer[] addr;
- Integer[] input;
- Integer[] advanceFrames;
- Strat(String name, int cost, Integer[] addr, Integer[] input, Integer[] advanceFrames) {
- this.addr = addr;
- this.cost = cost;
- this.name = name;
- this.input = input;
- this.advanceFrames = advanceFrames;
- }
- public void execute(GBWrapper wrap) {
- for (int i = 0; i < addr.length; i++) {
- wrap.advanceToAddress(addr[i]);
- wrap.injectRBInput(input[i]);
- for (int j = 0; j < advanceFrames[i]; j++) {
- wrap.advanceFrame();
- }
- }
- }
- }
- static class IntroSequence extends ArrayList<Strat> implements Comparable<IntroSequence> {
- private static final long serialVersionUID = -7505108790448829235L;
- IntroSequence(Strat... strats) {
- super(Arrays.asList(strats));
- }
- IntroSequence(IntroSequence other) {
- super(other);
- }
- @Override
- public String toString() {
- String ret = gameName;
- for (Strat s : this) {
- ret += s.name;
- }
- return ret;
- }
- void execute(GBWrapper wrap) {
- for (Strat s : this) {
- s.execute(wrap);
- }
- }
- int cost() {
- return this.stream().mapToInt((Strat s) -> s.cost).sum();
- }
- @Override
- public int compareTo(IntroSequence o) {
- return this.cost() - o.cost();
- }
- }
- private static boolean travellingToWarp(int map, int x, int y) {
- if (map == 59) {
- if (x == 5 && y == 5) {
- return true;
- } else if (x == 17 && y == 11) {
- return true;
- }
- } else if (map == 60) {
- if (x == 25 && y == 9) {
- return true;
- } else if (x == 17 && y == 11) {
- return true;
- } else if (x == 21 && y == 17) {
- return true;
- }
- } else {
- if (x == 25 && y == 9) {
- return true;
- }
- }
- return false;
- }
- private static class PalStrat extends Strat {
- PalStrat(String name, int cost, Integer[] addr, Integer[] input, Integer[] advanceFrames) {
- super(name, cost, addr, input, advanceFrames);
- }
- @Override
- public void execute(GBWrapper wrap) {
- for (int i = 0; i < addr.length; i++) {
- wrap.advanceWithJoypadToAddress(input[i], addr[i]);
- wrap.advanceFrame(input[i]);
- for (int j = 0; j < advanceFrames[i]; j++) {
- wrap.advanceFrame();
- }
- }
- }
- }
- private static Strat nido0 = new Strat("_hop0", 0, new Integer[] { RedBlueAddr.joypadAddr }, new Integer[] { UP | SELECT | B }, new Integer[] { 1 });
- private static Strat nido1 = new Strat("_hop1", 131, new Integer[] { RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.joypadAddr }, new Integer[] { NO_INPUT, NO_INPUT, A }, new Integer[] { 0, 0, 1 });
- private static Strat nido2 = new Strat("_hop2", 190, new Integer[] { RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.joypadAddr }, new Integer[] { NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, A }, new Integer[] { 0, 0, 0, 0, 1 });
- private static Strat nido3 = new Strat("_hop3", 298, new Integer[] { RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.joypadAddr }, new Integer[] { NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, A }, new Integer[] { 0, 0, 0, 0, 0, 0, 1 });
- private static Strat nido4 = new Strat("_hop4", 447, new Integer[] { RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.animateNidorinoAddr, RedBlueAddr.checkInterruptAddr, RedBlueAddr.joypadAddr }, new Integer[] { NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, NO_INPUT, A }, new Integer[] { 0, 0, 0, 0, 0, 0, 0, 0, 1 });
- private static Strat nido5 = new Strat("_hop5", 536, new Integer[] { RedBlueAddr.displayTitleScreenAddr }, new Integer[] { NO_INPUT }, new Integer[] { 0 });
- private static Strat cont = new Strat("", 0, new Integer[] { RedBlueAddr.joypadAddr }, new Integer[] { A }, new Integer[] { 1 });
- private static Strat backout = new Strat("_backout", 97, new Integer[] { RedBlueAddr.joypadAddr }, new Integer[] { B }, new Integer[] { 1 });
- private static Strat gfSkip = new Strat("_gfskip", 0, new Integer[] { RedBlueAddr.joypadAddr }, new Integer[] { UP | SELECT | B }, new Integer[] { 1 });
- private static Strat gfWait = new Strat("_gfwait", 253, new Integer[] { RedBlueAddr.delayAtEndOfShootingStarAddr }, new Integer[] { NO_INPUT }, new Integer[] { 0 });
- private static Strat title0 = new Strat("", 0, new Integer[] { RedBlueAddr.joypadAddr }, new Integer[] { START }, new Integer[] { 1 });
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement