diff --git a/app/build.gradle b/app/build.gradle index f49e875..6e7d174 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "com.thisispiri.mnk" minSdkVersion 14 targetSdkVersion 28 - versionCode 29 - versionName "1.11.1" + versionCode 30 + versionName "1.12.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/app/src/main/java/com/thisispiri/mnk/EmacsGomokuAi.kt b/app/src/main/java/com/thisispiri/mnk/EmacsGomokuAi.kt index 902ca44..0546bea 100644 --- a/app/src/main/java/com/thisispiri/mnk/EmacsGomokuAi.kt +++ b/app/src/main/java/com/thisispiri/mnk/EmacsGomokuAi.kt @@ -46,7 +46,7 @@ open class EmacsGomokuAi: MnkAi { private fun checkTuples(mode: Mode, values: Array>) { val po = Point(if(mode == Mode.RESLASH) game.horSize - 1 else 0, 0) while(game.inBoundary(po.y, po.x)) { - val count: Array = arrayOf(0, 0) //count[0] == ownCount, count[1] == enemCount. TODO: use separate variables? + val count: Array = arrayOf(0, 0) //count[0] == ownCount, count[1] == enemCount. val tuple: Queue = ArrayDeque() val pi = Point(po) while(game.inBoundary(pi.y, pi.x)) { diff --git a/app/src/main/java/com/thisispiri/mnk/MnkGame.java b/app/src/main/java/com/thisispiri/mnk/MnkGame.java index 0e0bd45..92ffb1f 100644 --- a/app/src/main/java/com/thisispiri/mnk/MnkGame.java +++ b/app/src/main/java/com/thisispiri/mnk/MnkGame.java @@ -7,7 +7,7 @@ import java.util.Stack; /**A representation of an MNK game.*/ -public class MnkGame { +public class MnkGame { //TODO: Support renju /**The state of the board, on which lie the {@link Shape}s of the game.*/ public Shape[][] array; /**The array of shapes to be placed rotationally in a normal game.*/ diff --git a/app/src/main/java/com/thisispiri/mnk/andr/MainActivity.java b/app/src/main/java/com/thisispiri/mnk/andr/MainActivity.java index 32282bc..d796abd 100644 --- a/app/src/main/java/com/thisispiri/mnk/andr/MainActivity.java +++ b/app/src/main/java/com/thisispiri/mnk/andr/MainActivity.java @@ -120,7 +120,7 @@ public class MainActivity extends AppCompatActivity implements MnkManager, Timed private final static int SAVE_REQUEST_CODE = 412, LOAD_REQUEST_CODE = 413, LOCATION_REQUEST_CODE = 414, BLUETOOTH_ENABLE_CODE = 415; private final static int REQUEST_RECEIVED_OUTSIDE_MAIN = 416; private final static String DECISION_TAG = "decision", EDITTEXT_TAG = "file", BLUETOOTH_TAG = "bluetooth", CHECKS_TAG = "checks"; - private final static String DIRECTORY_NAME = "PIRI MNK", FILE_EXTENSION = ".sgf"; + private final static String DIRECTORY_NAME = "PIRI/MNK", FILE_EXTENSION = ".sgf"; /**The {@code Map} mapping {@link Info}s to IDs of {@code String}s that are displayed when the {@code Activity} receives them from the {@link IoThread}.*/ private final static Map ioMessages; private final static MnkAi[] availableAis = {new FillerMnkAi(), new PiriMnkAi(), new EmacsGomokuAi()}; @@ -489,7 +489,7 @@ private void requestConfirm(Bundle arguments, String message) { requestConfirm(arguments, message, null, null); } /**Shows an {@code EditTextDialogFragment} with the supplied tag, message and hint.*/ - private void showEditTextDialog(final String message, final String hint) { + private void showEditTextDialog(final String message, final String hint) { //TODO: Move to PIRI Dialogs EditTextDialogFragment fragment = new EditTextDialogFragment(); fragment.setArguments(bundleWith(getString(R.string.i_tagInBundle), EDITTEXT_TAG)); fragment.show(getSupportFragmentManager(), EDITTEXT_TAG, message, hint); @@ -629,7 +629,9 @@ else if(!adapter.isEnabled()) { @Override public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { if(requestCode == BLUETOOTH_ENABLE_CODE) { if(resultCode == RESULT_OK) - displayDialog = BLUETOOTH_ENABLE_CODE; //IllegalStateException is thrown if we call DialogFragment.show() directly. onResumeFragments() will call it indirectly by calling showBluetoothDialog() + //IllegalStateException is thrown if we call DialogFragment.show() here(https://stackoverflow.com/q/33264031). + //saveGame() calls show(), so we call that in onResumeFragments() + displayDialog = BLUETOOTH_ENABLE_CODE; else { hiddenClick(radioLocal); showToast(this, R.string.enableBluetooth); @@ -741,7 +743,9 @@ else if(i >= 4) { //For gravity and exactOnly startActivityForResult(enableBtIntent, BLUETOOTH_ENABLE_CODE); return; } - displayDialog = requestCode; //IllegalStateException is thrown if we call DialogFragment.show() directly. onResumeFragments() will indirectly call it by calling saveGame() or loadGame() + //IllegalStateException is thrown if we call DialogFragment.show() here(https://stackoverflow.com/q/33264031). + //saveGame() calls show(), so we call that in onResumeFragments() + displayDialog = requestCode; } else if(requestCode == LOCATION_REQUEST_CODE) hiddenClick(radioLocal); @@ -756,31 +760,27 @@ else if(requestCode == LOCATION_REQUEST_CODE) * @param fileName If null, shows a {@code Dialog} prompting the user to input the file name. If not, saves the game.*/ private void saveGame(final String fileName) { if(fileName == null) showEditTextDialog(getString(R.string.save), getString(R.string.fileNameHint)); - else { - try { - saveLoader.save(game, getFile(DIRECTORY_NAME, fileName + FILE_EXTENSION, true)); - } - catch (IOException e) { - showToast(this, R.string.couldntCreateFile); - } + else try { + saveLoader.save(game, getFile(DIRECTORY_NAME, fileName + FILE_EXTENSION, true)); + } + catch (IOException e) { + showToast(this, R.string.couldntCreateFile); } } /**Loads the game. * @param fileName If null, shows a {@code Dialog} prompting the user to input the file name. If not, loads the game.*/ private void loadGame(final String fileName) { if(fileName == null) showEditTextDialog(getString(R.string.load), getString(R.string.fileNameHint)); - else { - try { - MnkGame loaded = saveLoader.load(getFile(DIRECTORY_NAME, fileName + FILE_EXTENSION, false), game.winStreak); - initialize(); //Initialize after loading the game so that if loading fails, the previous game doesn't get initialized - game = new LegalMnkGame(loaded); - board.setGame(game); - board.invalidate(); - highlighter.updateValues(game.getHorSize(), game.getVerSize(), screenX); - } - catch (IOException e) { - showToast(this, R.string.couldntFindFile); - } + else try { + MnkGame loaded = saveLoader.load(getFile(DIRECTORY_NAME, fileName + FILE_EXTENSION, false), game.winStreak); + initialize(); //Initialize after loading the game so that if loading fails, the previous game doesn't get initialized + game = new LegalMnkGame(loaded); + board.setGame(game); + board.invalidate(); + highlighter.updateValues(game.getHorSize(), game.getVerSize(), screenX); + } + catch (IOException e) { + showToast(this, R.string.couldntFindFile); } } @@ -798,7 +798,8 @@ private class FillThread extends Thread { @Override synchronized public void run() { while(!gameEnd) { aiTurn(false); - //If it doesn't wait until the UI thread finishes and keep calling aiTurn, most of board.invalidate() calls will be ignored and the result will be shown at once when the game's end, breaking animation. + //If it doesn't wait until the UI thread finishes and keeps calling aiTurn, most of board.invalidate() + //calls will be ignored and the result will be shown at once when the game ends, breaking animation. try { wait(); } catch(InterruptedException e) { break; } }