diff options
42 files changed, 1407 insertions, 1443 deletions
diff --git a/core/src/ch/asynk/rustanddust/engine/Board.java b/core/src/ch/asynk/rustanddust/engine/Board.java index ace94d6..f7fed7e 100644 --- a/core/src/ch/asynk/rustanddust/engine/Board.java +++ b/core/src/ch/asynk/rustanddust/engine/Board.java @@ -18,9 +18,6 @@ import ch.asynk.rustanddust.engine.util.IterableSet; import ch.asynk.rustanddust.engine.util.Collection; import ch.asynk.rustanddust.engine.gfx.Moveable; import ch.asynk.rustanddust.engine.gfx.Animation; -import ch.asynk.rustanddust.engine.gfx.animations.AnimationSequence; -import ch.asynk.rustanddust.engine.gfx.animations.RunnableAnimation; -import ch.asynk.rustanddust.engine.gfx.animations.MoveToAnimation.MoveToAnimationCb; public abstract class Board implements Disposable, Animation { @@ -404,7 +401,7 @@ public abstract class Board implements Disposable, Animation } } - return entry.opposite(); + return entry; } public int objectivesCount(Faction faction) @@ -491,7 +488,6 @@ public abstract class Board implements Disposable, Animation public Pawn setPawnOnto(Pawn pawn, Move move) { - pawn.move(move); return setPawnOnto(pawn, move.to, move.orientation); } @@ -502,54 +498,6 @@ public abstract class Board implements Disposable, Animation return pawn; } - private RunnableAnimation getSetPawnOntoAnimation(final Pawn pawn) - { - return RunnableAnimation.get(pawn, new Runnable() { - @Override - public void run() { - Tile to = pawn.move.to; - if (!to.isOffMap()) - setPawnOnto(pawn, to, pawn.move.orientation); - } - }); - } - - protected void movePawn(final Pawn pawn, Move move, MoveToAnimationCb cb) - { - pawn.move(move); - removePawn(pawn); - - AnimationSequence seq = pawn.getMoveAnimation(move.iterator(), (move.steps() + 1), cb); - seq.addAnimation(getSetPawnOntoAnimation(pawn)); - addAnimation(seq); - } - - protected void enterPawn(final Pawn pawn, Move move) - { - pawn.move(move); - setPawnOnto(pawn, move.to, move.orientation); - } - - protected void revertLastPawnMove(final Pawn pawn, final Move move) - { - removePawn(pawn); - - revertclaim(pawn, move.to); - for (Tile tile : move.tiles) - revertclaim(pawn, tile); - claim(pawn, move.from); - - AnimationSequence seq = pawn.getRevertLastMoveAnimation(1); - seq.addAnimation(RunnableAnimation.get(pawn, new Runnable() { - @Override - public void run() { - pushPawnOnto(pawn, pawn.getTile()); - } - })); - addAnimation(seq); - pawn.revertLastMove(); - } - public void attack(final Pawn pawn, final Pawn target, boolean clearVisibility) { if (!pawn.canEngage(target) || !searchBoard.canAttack(pawn, target, clearVisibility)) diff --git a/core/src/ch/asynk/rustanddust/engine/Move.java b/core/src/ch/asynk/rustanddust/engine/Move.java index 09e7330..ff927c0 100644 --- a/core/src/ch/asynk/rustanddust/engine/Move.java +++ b/core/src/ch/asynk/rustanddust/engine/Move.java @@ -49,11 +49,10 @@ public class Move extends Path implements Iterable<Vector3>, Iterator movePool.clear(); } - public static Move getEnter(Pawn pawn, Tile to, Orientation orientation) + public static Move getEnter(Pawn pawn, Tile from, Tile to, Orientation orientation, Path path) { - Move m = get(pawn, null, to, orientation, null); + Move m = get(pawn, from, to, orientation, path); m.type = MoveType.ENTER; - m.cost = to.costFrom(pawn, orientation); return m; } @@ -122,11 +121,6 @@ public class Move extends Path implements Iterable<Vector3>, Iterator return (type == MoveType.REGULAR); } - public boolean isFinal() - { - return (type != MoveType.ENTER); - } - public int steps() { int steps = 0; diff --git a/core/src/ch/asynk/rustanddust/engine/PathBuilder.java b/core/src/ch/asynk/rustanddust/engine/PathBuilder.java index edac1c3..609fe8b 100644 --- a/core/src/ch/asynk/rustanddust/engine/PathBuilder.java +++ b/core/src/ch/asynk/rustanddust/engine/PathBuilder.java @@ -294,6 +294,18 @@ public class PathBuilder implements Disposable return Move.get(pawn, from, to, orientation, getPath(0)); } + public Move getEnterMove(Pawn pawn, Tile from) + { + // getPath(0).tiles.insert(this.from, 0); + // this.from = from; + int cost = pawn.getSpentMovementPoints(); + pawn.reset(); + Move move = getMove(); + move.type = Move.MoveType.ENTER; + move.cost = cost + ((this.from == this.to) ? 0 : move.cost); + return move; + } + public Move getExitMove() { Move move = getMove(); diff --git a/core/src/ch/asynk/rustanddust/engine/Pawn.java b/core/src/ch/asynk/rustanddust/engine/Pawn.java index fc0323f..d7c8749 100644 --- a/core/src/ch/asynk/rustanddust/engine/Pawn.java +++ b/core/src/ch/asynk/rustanddust/engine/Pawn.java @@ -115,20 +115,14 @@ public abstract class Pawn implements Moveable, Disposable { switch(move.type) { - case REGULAR: - if ((this.move != null) && (!this.move.isEnter())) - throw new RuntimeException("try to override an existing move instance"); + case SET: break; + case REGULAR: case ENTER: - if (this.move != null) - throw new RuntimeException("try to override an existing move instance"); - break; case EXIT: if (this.move != null) throw new RuntimeException("try to override an existing move instance"); break; - case SET: - break; default: throw new RuntimeException("unsupported MoveType"); } @@ -144,11 +138,6 @@ public abstract class Pawn implements Moveable, Disposable attack.distance = distance; } - public boolean justEntered() - { - return ((move != null) && move.isEnter()); - } - public boolean is(Faction faction) { return (this.faction == faction); @@ -333,28 +322,17 @@ public abstract class Pawn implements Moveable, Disposable return hasOverlayEnabled(); } - public AnimationSequence getRotateAnimation(float z, int size) - { - prevPosition.set(position); - AnimationSequence seq = AnimationSequence.get(1 + size); - seq.addAnimation(MoveToAnimation.get(this, position.x, position.y, z, MOVE_TIME)); - - return seq; - } - - public AnimationSequence getMoveAnimation(Iterator<Vector3> vectors, int size, MoveToAnimation.MoveToAnimationCb cb) + public AnimationSequence getMoveAnimation(Iterator<Vector3> vectors, AnimationSequence seq, MoveToAnimation.MoveToAnimationCb cb) { prevPosition.set(position); - AnimationSequence seq = AnimationSequence.get(size); while (vectors.hasNext()) seq.addAnimation(MoveToAnimation.get(this, vectors.next(), MOVE_TIME, cb)); return seq; } - public AnimationSequence getRevertLastMoveAnimation(int size) + public AnimationSequence getRevertLastMoveAnimation(AnimationSequence seq) { - AnimationSequence seq = AnimationSequence.get(2 + size); seq.addAnimation(MoveToAnimation.get(this, prevPosition, MOVE_TIME)); seq.addAnimation(RunnableAnimation.get(this, new Runnable() { @Override diff --git a/core/src/ch/asynk/rustanddust/game/Battle.java b/core/src/ch/asynk/rustanddust/game/Battle.java index 168f5ee..4ed139c 100644 --- a/core/src/ch/asynk/rustanddust/game/Battle.java +++ b/core/src/ch/asynk/rustanddust/game/Battle.java @@ -24,14 +24,12 @@ public interface Battle extends Marshal public Player getOpponent(); - public void init(); + public Map init(Ctrl ctrl); public void desinit(); public void initialDeployment(); - public boolean actionDone(); - public boolean turnDone(); public boolean isDeploymentDone(); diff --git a/core/src/ch/asynk/rustanddust/game/Config.java b/core/src/ch/asynk/rustanddust/game/Config.java index 318eae9..db7fb5c 100644 --- a/core/src/ch/asynk/rustanddust/game/Config.java +++ b/core/src/ch/asynk/rustanddust/game/Config.java @@ -37,9 +37,10 @@ public class Config public enum LoadMode { - LOAD("Load", 0), - REPLAY_LAST("Replay Last Turn", 1), - REPLAY_ALL("Full Replay", 2); + NEW("New", 0), + RESUME("Resume", 1), + REPLAY_CURRENT("Replay Current Turn", 2), + REPLAY_ALL("Full Replay", 3); public String s; public int i; LoadMode(String s, int i) @@ -101,9 +102,9 @@ public class Config public Config() { this.gameMode = GameMode.SOLO; - this.loadMode = LoadMode.LOAD; + this.loadMode = LoadMode.NEW; this.debug = false; - this.autoPath = true; + this.autoPath = false; this.revertAllMoves = false; this.showMoves = true; this.showTargets = true; diff --git a/core/src/ch/asynk/rustanddust/game/Ctrl.java b/core/src/ch/asynk/rustanddust/game/Ctrl.java index 6ec7184..9ff5d53 100644 --- a/core/src/ch/asynk/rustanddust/game/Ctrl.java +++ b/core/src/ch/asynk/rustanddust/game/Ctrl.java @@ -18,32 +18,54 @@ import ch.asynk.rustanddust.game.State.StateType; import ch.asynk.rustanddust.game.states.StateCommon; import ch.asynk.rustanddust.game.states.StateSelect; import ch.asynk.rustanddust.game.states.StateMove; -import ch.asynk.rustanddust.game.states.StateRotate; import ch.asynk.rustanddust.game.states.StatePromote; import ch.asynk.rustanddust.game.states.StateEngage; -import ch.asynk.rustanddust.game.states.StateBreak; import ch.asynk.rustanddust.game.states.StateAnimation; -import ch.asynk.rustanddust.game.states.StateReinforcement; import ch.asynk.rustanddust.game.states.StateDeployment; -import ch.asynk.rustanddust.game.states.StateWithdraw; +import ch.asynk.rustanddust.game.states.StateReinforcement; import ch.asynk.rustanddust.game.states.StateReplay; public abstract class Ctrl implements Disposable { - public enum EventType + enum Mode { - STATE_CHANGE, - HUD_ANSWER, + LOADING, + REPLAY, + PLAY, + } + + private static final boolean debugCtrl = false; + + public enum MsgType + { + OK, + CANCEL, + PROMOTE, ANIMATIONS_DONE, + UNIT_DOCK_SELECT, UNIT_DOCK_TOGGLE, - UNIT_DOCK_SELECT; + UNIT_DEPLOYED, + UNIT_UNDEPLOYED, + } + + public enum EventType + { + ORDER, + ORDER_DONE, + STATE_CHANGE, + ANIMATION, + REPLAY_DONE, + TURN_DONE, + ACTION_ABORTED, + EXIT_BATTLE, } class Event { public EventType type; public Object data; - public boolean status; + @Override + public String toString() { return String.format("Event : %s - %s", type, (data == null) ? "" : data); } } public final RustAndDust game; @@ -55,39 +77,37 @@ public abstract class Ctrl implements Disposable public Map map; public Hud hud; + private float blockEvents; public boolean blockMap; public boolean blockHud; private Hex touchedHex; + protected int gameId; protected boolean synched; private int depth; + private Order lastOrder; + private final State selectState; - private final State pathState; - private final State rotateState; + private final State moveState; private final State promoteState; private final State engageState; - private final State breakState; private final State animationState; - private final State reinforcementState; private final State deploymentState; - private final State withdrawState; + private final State reinforcementState; private final State replayState; - private int animationCount = 0; - + private Mode mode; private State state; private StateType stateType; private StateType stateAfterAnimation; public abstract void init(); - protected abstract void actionDoneCb(); - protected abstract void turnDoneCb(); - public abstract void orderProcessedCb(); public static Ctrl getCtrl(final RustAndDust game) { Ctrl ctrl = null; - switch(game.config.gameMode) { + switch(game.config.gameMode) + { case SOLO: ctrl = new Solo(game); break; @@ -102,57 +122,57 @@ public abstract class Ctrl implements Disposable this.battle = game.config.battle; this.hud = new Hud(game); - this.blockMap = false; + this.blockEvents = 0.5f; + this.blockMap = true; this.blockHud = false; this.touchedHex = null; + this.gameId = -1; this.synched = false; this.depth = 0; + this.lastOrder = null; + this.selectState = new StateSelect(); - this.pathState = new StateMove(); - this.rotateState = new StateRotate(); + this.moveState = new StateMove(); this.promoteState = new StatePromote(); this.engageState = new StateEngage(); - this.breakState = new StateBreak(); this.animationState = new StateAnimation(); - this.reinforcementState = new StateReinforcement(); this.deploymentState = new StateDeployment(); - this.withdrawState = new StateWithdraw(); + this.reinforcementState = new StateReinforcement(); this.replayState = new StateReplay(); - this.stateType = StateType.LOADING; + this.mode = Mode.LOADING; - battle.init(); - this.map = battle.getMap(); + this.map = battle.init(this); init(); StateCommon.set(game); hud.update(); - this.state = selectState; - this.stateType = StateType.DONE; - this.stateAfterAnimation = StateType.DONE; - - setState(battle.getState()); + this.stateType = StateType.WAIT_EVENT; + this.stateAfterAnimation = battle.getState(); - if (synched) { - this.hud.notify(battle.toString(), 2, Position.MIDDLE_CENTER, false); - return; - } + setState(StateType.ANIMATION); - switch(game.config.loadMode) { - case REPLAY_ALL: - // TODO REPLAY_ALL + switch(game.config.loadMode) + { + case NEW: + this.hud.notify(battle.toString(), 2, Position.MIDDLE_CENTER, false); break; - case REPLAY_LAST: - map.prepareReplayLastTurn(); - setState(StateType.REPLAY); + case RESUME: + if (!synched) { + map.prepareReplayLastAction(); + this.stateAfterAnimation = StateType.REPLAY; + } break; - case LOAD: - map.prepareReplayLastAction(); - setState(StateType.REPLAY); + case REPLAY_CURRENT: + map.prepareReplayCurrentTurn(); + this.stateAfterAnimation = StateType.REPLAY; + break; + case REPLAY_ALL: + // TODO REPLAY ALL + this.stateAfterAnimation = StateType.REPLAY; break; } - } @Override @@ -167,13 +187,9 @@ public abstract class Ctrl implements Disposable // JSON - protected boolean isLoading() - { - return (stateType == StateType.LOADING); - } - protected void load(Marshal.Mode mode, String payload) { + if (payload == null) return; JsonValue root = new JsonReader().parse(payload); battle.load(mode, root); } @@ -188,6 +204,27 @@ public abstract class Ctrl implements Disposable return writer.toString(); } + // DB + private void storeState() + { + game.db.storeGameState(gameId, battle.getTurnCount(), battle.getPlayer().id, unload(Marshal.Mode.PLAYERS), unload(Marshal.Mode.MAP)); + } + + private void storeOrders() + { + game.db.storeGameOrders(gameId, battle.getTurnCount(), battle.getPlayer().id, unload(Marshal.Mode.ORDERS)); + } + + private void clearOrders() + { + game.db.clearGameOrders(gameId); + } + + private void storeTurn() + { + game.db.storeCurrentTurn(gameId); + } + // INPUTS public boolean drag(float x, float y, int dx, int dy) @@ -199,9 +236,7 @@ public abstract class Ctrl implements Disposable public void touchDown(float hudX, float hudY, float mapX, float mapY) { - boolean inAnimation = (this.stateType == StateType.ANIMATION); - - if (!blockHud && hud.hit(hudX, hudY, inAnimation)) + if (!blockHud && hud.hit(hudX, hudY, inAnimation())) return; touchedHex = (blockMap ? null : map.getHexAt(mapX, mapY)); @@ -213,34 +248,64 @@ public abstract class Ctrl implements Disposable state.touch(touchedHex); } - // EVENTS + // MESSAGES - private Event getEvent() + public void sendMsg(MsgType msgType) { - Event evt = freeEvents.pop(); - if (evt == null) - evt = new Event(); - return evt; + sendMsg(msgType, null); } - public void postDone() { post(StateType.DONE); } - public void postAbort() { post(StateType.ABORT); } + public void sendMsg(MsgType msgType, Object data) + { + RustAndDust.debug(String.format("Msg : %s %s", msgType, data)); + switch(msgType) + { + case ANIMATIONS_DONE: animationsDone(); break; + case UNIT_DOCK_TOGGLE: unitDockToggle(); break; + case UNIT_DEPLOYED: deploymentState.processMsg(msgType, data); break; + default: + if (!this.state.processMsg(msgType, data)) + RustAndDust.error(String.format("%s does not handle msg : %s %s", this.state, msgType, data)); + break; + } + } + + // EVENTS + + public void postTurnDone() { postEvent(EventType.TURN_DONE); } + public void postActionAborted() { postEvent(EventType.ACTION_ABORTED); } + public void postReplayDone(StateType stateType) { postEvent(EventType.REPLAY_DONE, stateType); } public void post(StateType stateType) { - Event evt = getEvent(); - evt.type = EventType.STATE_CHANGE; - evt.data = stateType; - events.enqueue(evt); + postEvent(EventType.STATE_CHANGE, stateType); } - public void postAnswer(Hud.OkCancelAction what, boolean status) + public void postOrder(Order order) { - Event evt = getEvent(); - evt.type = EventType.HUD_ANSWER; - evt.data = what; - evt.status = status; - events.enqueue(evt); + postOrder(order, null); + } + + public void postInitOrder(Order order) + { + // postEvent(EventType.ORDER, order); + // postEvent(EventType.ORDER_DONE, stateType); + executeOrder(order); + orderDone(null); + } + + public void postOrder(Order order, StateType stateType) + { + postEvent(EventType.ORDER, order); + switch(order.type) + { + case END: + case REVERT: + break; + default: + postEvent(EventType.ANIMATION, StateType.WAIT_EVENT); + } + postEvent(EventType.ORDER_DONE, stateType); } public void postEvent(EventType type) @@ -250,33 +315,39 @@ public abstract class Ctrl implements Disposable public void postEvent(EventType type, Object data) { - Event evt = getEvent(); + Event evt = freeEvents.pop(); + if (evt == null) + evt = new Event(); evt.type = type; evt.data = data; events.enqueue(evt); } - public void processEvent() + public void processEvent(float delta) { - if (events.size() <= 0) + if (blockEvents > 0f) { + blockEvents -= delta; + if (blockEvents > 0f) + return; + } + if ((events.size() <= 0) || inAnimation()) return; Event evt = events.dequeue(); - switch(evt.type) { - case STATE_CHANGE: - setState((StateType) evt.data); - break; - case HUD_ANSWER: - handleHudAnswer(evt); - break; - case ANIMATIONS_DONE: - animationsDone(); - break; - case UNIT_DOCK_TOGGLE: - unitDockToggle(); - break; - case UNIT_DOCK_SELECT: - unitDockSelect((Unit) evt.data); + RustAndDust.debug(evt.toString()); + + switch(evt.type) + { + case ORDER: executeOrder((Order) evt.data); break; + case ORDER_DONE: orderDone((StateType) evt.data); break; + case STATE_CHANGE: setState((StateType) evt.data); break; + case REPLAY_DONE: replayDone((StateType) evt.data); break; + case TURN_DONE: turnDone(); break; + case ACTION_ABORTED: abortAction(); break; + case EXIT_BATTLE: exitBattle(); break; + case ANIMATION: + stateAfterAnimation = (StateType) evt.data; + setState(StateType.ANIMATION); break; default: RustAndDust.error(String.format("Unhandled Event Type : %s %s", evt.type, evt.data)); @@ -284,243 +355,244 @@ public abstract class Ctrl implements Disposable freeEvents.push(evt); } - // State callbacks - - public void setAfterAnimationState(StateType after) + private boolean inAnimation() { - stateAfterAnimation = after; - } - - // Event handlers - - private void handleHudAnswer(Event evt) - { - switch((Hud.OkCancelAction) evt.data) { - case EXIT_BOARD: - if (evt.status) setState(StateType.DONE); - else setState(StateType.ABORT); - break; - case ABORT_TURN: - if (evt.status) { - this.state.abort(); - turnDone(); - } - break; - case END_DEPLOYMENT: - if (evt.status) { - this.state.execute(); - turnDone(); - } - break; - case QUIT_BATTLE: - if (evt.status) - game.switchToMenu(); - break; - - } + return (this.stateType == StateType.ANIMATION); } private void animationsDone() { + if (debugCtrl) RustAndDust.debug(" ANIMATIONS DONE"); + if (hud.dialogActive()) hud.notifyAnimationsDone(); - if (stateType == StateType.ANIMATION) { - StateType tmp = stateAfterAnimation; - stateAfterAnimation = StateType.DONE; - setState(tmp); + + if (mode == Mode.LOADING) { + this.mode = ((stateAfterAnimation == StateType.REPLAY) ? Mode.REPLAY : Mode.PLAY); + if (game.config.loadMode == Config.LoadMode.NEW) { + storeState(); + storeTurn(); + } + if (mode == Mode.PLAY) + map.clear(true); } + this.blockMap = false; + StateType tmp = stateAfterAnimation; + stateAfterAnimation = StateType.WAIT_EVENT; + setState(tmp); } - private void unitDockSelect(Unit unit) + private void replayDone(StateType nextState) { - if ((stateType == StateType.DEPLOYMENT) || (stateType == StateType.REINFORCEMENT)) - state.touch(null); + if (debugCtrl) RustAndDust.debug(" REPLAY DONE"); + hud.notify("Replay Done", Position.MIDDLE_CENTER); + this.mode = Mode.PLAY; + if (nextState != null) { + setState(nextState); + } else { + if (!synched) { + storeState(); + synched = true; + } + if (battle.getPlayer().apExhausted()) + postTurnDone(); + else if (!battle.getPlayer().canDoSomething()) + postTurnDone(); + else + setState(battle.getState()); + } } - private void unitDockToggle() + private void executeOrder(Order order) { - if (this.stateType == StateType.SELECT) - setState(StateType.REINFORCEMENT); - else if (this.stateType == StateType.REINFORCEMENT) - setState(StateType.SELECT); + if (debugCtrl) RustAndDust.debug(" EXECUTE ORDER"); + lastOrder = order; + map.execute(order); + if ((order.type == Order.OrderType.ENGAGE) && !order.replay) { + game.ctrl.hud.engagementSummary(order.engagement); + } + if (this.mode == Mode.PLAY) + storeOrders(); + hud.update(); } - // - - private void turnDone() + private void orderDone(StateType nextState) { - if (battle.turnDone()) - hud.victory(battle.getPlayer(), battle.getOpponent()); - else { - if (battle.getPlayer().hasReinforcement()) - hud.notify("You have reinforcement", 2, Position.MIDDLE_CENTER, true); - hud.update(); - if (!battle.getPlayer().canDoSomething()) { - hud.notify("No available Actions"); - setState(StateType.TURN_OVER); - } else - setState(battle.getState()); - } - } + if (debugCtrl) RustAndDust.debug(" ORDER DONE -> " + nextState); + Order order = this.lastOrder; + this.lastOrder = null; + if (nextState == null) + nextState = battle.getState(); - // + completeOrder(order); - private void setState(StateType nextState) - { - depth += 1; - if (depth > 1) - RustAndDust.error(String.format("***!!!*** STATE DEPTH : %d", depth)); + if (mode == Mode.LOADING) + return; - if (nextState == StateType.ABORT) - nextState = abortAction(); - else if (nextState == StateType.DONE) { - nextState = complete(); + if (mode == Mode.REPLAY) { + if (order.cost > 0) + battle.getPlayer().burnDownOneAp(); + hud.update(); + blockEvents = 0.2f; + post(nextState); + return; } - if (stateType == StateType.ANIMATION) { - this.blockMap = hud.dialogActive(); - if (nextState == StateType.REPLAY) - completeReplayStep(); + if (order.cost == 0) { + post(nextState); + return; } - hud.playerInfo.blockEndOfTurn(nextState != StateType.SELECT); - - if (nextState == stateType) - RustAndDust.debug(String.format("***!!!*** STATE LOOP : %s", stateType)); - - this.state.leaveFor(nextState); - - this.state = getNextState(nextState); - - StateType tmp = stateType; - stateType = nextState; + battle.getPlayer().burnDownOneAp(); + hud.notify("1 Action Point burnt"); + hud.update(); - this.state.enterFrom(tmp); + if (battle.getPlayer().apExhausted()) { + hud.notify("No more Action Points"); + postTurnDone(); + } else if (!battle.getPlayer().canDoSomething()) { + hud.notify("No available Actions"); + postTurnDone(); + } else { + post(nextState); + } - if (nextState == StateType.TURN_OVER) - turnDone(); - depth -= 1; + storeState(); } - private StateType complete() + private void completeOrder(Order order) { - switch(stateType) { - case DEPLOYMENT: - return completeDeployment(); - case REPLAY: - return completeReplay(); - default: - return completeAction(); + switch(order.type) + { + case MOVE: completeMoveOrder(order, (Unit) order.move.pawn); break; + case ENGAGE: completeEngagementOrder(order, order.engagement.defender); break; + case PROMOTE: battle.getPlayer().promote(order.leader); break; + case REVERT: break; + case END: break; + default: break; } } - private StateType completeDeployment() + private void completeEngagementOrder(Order order, Unit unit) { - if (battle.isDeploymentDone()) - hud.askEndDeployment(); - battle.actionDone(); - return StateType.DEPLOYMENT; + if (order.engagement.success) { + battle.getPlayer().engagementWon += 1; + battle.getOpponent().casualty(unit); + } else { + battle.getPlayer().engagementLost += 1; + } } - private StateType abortAction() + private void completeMoveOrder(Order order, Unit unit) { - hud.notify("Action canceled"); - StateType nextState = this.state.abort(); - - if (nextState == StateType.ABORT) - nextState = battle.getState(); - - return nextState; + switch(order.move.type) + { + case EXIT: battle.getPlayer().unitWithdraw(unit); break; + case SET: battle.getPlayer().unitEntry(unit); break; + case ENTER: battle.getPlayer().unitEntry(unit); break; + case REGULAR: break; + default: break; + } } - private StateType completeAction() + private void turnDone() { - StateType nextState = this.state.execute(); + if (debugCtrl) RustAndDust.debug(" TURN DONE"); - if (nextState == StateType.DONE) { - if (battle.actionDone()) { - hud.notify("1 Action Point burnt"); - hud.update(); - } - if (battle.getPlayer().apExhausted()) { - hud.notify("No more Action Points"); - nextState = StateType.TURN_OVER; - } else if (!battle.getPlayer().canDoSomething()) { + setState(StateType.WAIT_EVENT); + + if (battle.turnDone()) + hud.victory(battle.getPlayer(), battle.getOpponent()); + else { + hud.update(); + if (battle.getPlayer().hasReinforcement()) + hud.notify("You have reinforcement", 2, Position.MIDDLE_CENTER, true); + if (!battle.getPlayer().canDoSomething()) { hud.notify("No available Actions"); - nextState = StateType.TURN_OVER; - } else - nextState = battle.getState(); + postTurnDone(); + } else { + post(battle.getState()); + } } - return nextState; + storeState(); + storeTurn(); + map.clear(true); + clearOrders(); } - private StateType completeReplay() + private void abortAction() { - if (battle.getPlayer().apExhausted()) { - return StateType.TURN_OVER; - } else if (!battle.getPlayer().canDoSomething()) { - return StateType.TURN_OVER; - } else - return battle.getState(); + if (debugCtrl) RustAndDust.debug(" ABORT ACTION"); + post(battle.getState()); } - private void completeReplayStep() + private void exitBattle() { - StateType nextState = replayState.execute(); + if (debugCtrl) RustAndDust.debug(" EXIT BATTLE"); + game.switchToMenu(); + } - if (nextState == StateType.DONE) { - battle.getPlayer().burnDownOneAp(); - hud.update(); + private void unitDockToggle() + { + if (this.stateType == StateType.SELECT) + post(StateType.REINFORCEMENT); + else if (this.stateType == StateType.REINFORCEMENT) { + sendMsg(MsgType.OK); + post(StateType.SELECT); } } - private State getNextState(StateType nextState) + // + + private void setState(StateType nextState) { - RustAndDust.debug("Ctrl", String.format(" %s -> %s : %s", stateType, nextState, battle.getPlayer())); + if (stateType == nextState) + RustAndDust.error("***!!!*** STATE LOOP ********************************************************************** " + stateType); - State state = this.state; + if (nextState == StateType.WAIT_EVENT) { + stateType = nextState; + if (debugCtrl) RustAndDust.debug(" WAIT_EVENT"); + return; + } - switch(nextState) { - case SELECT: - state = selectState; - break; - case MOVE: - state = pathState; - break; - case ROTATE: - state = rotateState; - break; - case PROMOTE: - state = promoteState; - break; - case ENGAGE: - state = engageState; - break; - case BREAK: - state = breakState; - break; - case WITHDRAW: - state = withdrawState; - break; - case ANIMATION: - state = animationState; - this.blockMap = true; - break; - case REINFORCEMENT: - state = reinforcementState; - break; - case DEPLOYMENT: - state = deploymentState; - break; - case REPLAY: - state = replayState; - break; + depth += 1; + if (depth > 1) + RustAndDust.error(String.format("***!!!*** STATE DEPTH : %d", depth)); + + if (nextState == StateType.DEPLOYMENT) { + if (battle.isDeploymentDone()) + hud.askEndDeployment(); + } + + hud.playerInfo.blockEndOfTurn(nextState != StateType.SELECT); + + this.state = getNextState(nextState); + StateType tmp = stateType; + stateType = nextState; + this.state.enterFrom(tmp); + + depth -= 1; + } + + private State getNextState(StateType nextState) + { + RustAndDust.debug(" State Change", String.format("%s -> %s", stateType, nextState)); + + switch(nextState) + { + case SELECT: return selectState; + case MOVE: return moveState; + case PROMOTE: return promoteState; + case ENGAGE: return engageState; + case ANIMATION: return animationState; + case DEPLOYMENT: return deploymentState; + case REINFORCEMENT: return reinforcementState; + case REPLAY: return replayState; default: RustAndDust.error(String.format("Unhandled State : %s", nextState)); - break; } - return state; + return this.state; } } diff --git a/core/src/ch/asynk/rustanddust/game/Engagement.java b/core/src/ch/asynk/rustanddust/game/Engagement.java index b9630b8..4c29c3d 100644 --- a/core/src/ch/asynk/rustanddust/game/Engagement.java +++ b/core/src/ch/asynk/rustanddust/game/Engagement.java @@ -35,6 +35,7 @@ public class Engagement implements Disposable, Pool.Poolable public Unit defender; public UnitList assists; public boolean success; + public int cost; public int d1; public int d2; public int d3; diff --git a/core/src/ch/asynk/rustanddust/game/Hex.java b/core/src/ch/asynk/rustanddust/game/Hex.java index 34ccdb3..ea988be 100644 --- a/core/src/ch/asynk/rustanddust/game/Hex.java +++ b/core/src/ch/asynk/rustanddust/game/Hex.java @@ -103,10 +103,10 @@ public class Hex extends Tile public int costFrom(Pawn pawn, Orientation side) { if (side == Orientation.KEEP) return 0; - if (hasUnits()) return (Integer.MAX_VALUE / 2); + if (hasUnits()) return Integer.MAX_VALUE; if (roadFrom(side)) return 1; - int c = 0; + int c = Integer.MAX_VALUE; switch(terrain) { case CLEAR: case HILLS: @@ -118,7 +118,6 @@ public class Hex extends Tile break; case OFFMAP: case BLOCKED: - c = (Integer.MAX_VALUE / 2); break; } diff --git a/core/src/ch/asynk/rustanddust/game/Hud.java b/core/src/ch/asynk/rustanddust/game/Hud.java index b58c8f1..936d8b0 100644 --- a/core/src/ch/asynk/rustanddust/game/Hud.java +++ b/core/src/ch/asynk/rustanddust/game/Hud.java @@ -218,12 +218,22 @@ public class Hud implements Disposable, Animation dialog.visible = false; if (dialog == okCancel) { - if (okCancel.ok) game.playEnter(); - else game.playType(); - ctrl.postAnswer(okCancelAction, okCancel.ok); + boolean ok = false; + if (okCancel.ok) { + ok = true; + game.playEnter(); + } else + game.playType(); + if (ok) { + if (this.okCancelAction == OkCancelAction.EXIT_BATTLE) + ctrl.postEvent(Ctrl.EventType.EXIT_BATTLE); + else + ctrl.sendMsg(Ctrl.MsgType.OK); + } else + ctrl.sendMsg(Ctrl.MsgType.CANCEL); } else if (dialog == stats) { game.playEnter(); - ctrl.postAnswer(OkCancelAction.EXIT_BATTLE, true); + ctrl.postEvent(Ctrl.EventType.EXIT_BATTLE); } else game.playType(); diff --git a/core/src/ch/asynk/rustanddust/game/Map.java b/core/src/ch/asynk/rustanddust/game/Map.java index f55b8fd..6a0bb03 100644 --- a/core/src/ch/asynk/rustanddust/game/Map.java +++ b/core/src/ch/asynk/rustanddust/game/Map.java @@ -24,33 +24,17 @@ public abstract class Map extends Map5Marshal meteorology = new Meteorology(); } - public void clearAll() + public void clear() { clear(false); } + public void clear(boolean orders) { + if (orders) { + RustAndDust.debug(" Map", String.format("Clearder Orders : %d", ordersSize())); + ordersClear(); + } clearMoves(); clearUnits(); } - public void actionDone() - { - incActionId(); - game.ctrl.actionDoneCb(); - } - - public void turnDone() - { - RustAndDust.debug("TurnDone", String.format(" Processed Orders : %d", ordersSize())); - game.ctrl.turnDoneCb(); - ordersClear(); - } - - @Override - protected int engagementCost(Engagement e) - { - if ((activatedUnits.size() == 1) && e.attacker.isA(Unit.UnitType.AT_GUN) && e.defender.isHardTarget()) - return 0; - return 1; - } - @Override protected void resolveEngagement(Engagement e) { @@ -116,6 +100,15 @@ public abstract class Map extends Map5Marshal e.d4 = 0; } + activableUnits.clear(); + if (success) { + for (Unit unit : activatedUnits) { + if (unit.canBreak()) + activableUnits.add(unit); + } + } + + e.cost = (((cnt == 1) && e.attacker.isA(Unit.UnitType.AT_GUN) && e.defender.isHardTarget()) ? 0 : 1); e.set(cnt, flk, def, tdf, wdf); e.success = success; } diff --git a/core/src/ch/asynk/rustanddust/game/Order.java b/core/src/ch/asynk/rustanddust/game/Order.java index b959628..528d4d7 100644 --- a/core/src/ch/asynk/rustanddust/game/Order.java +++ b/core/src/ch/asynk/rustanddust/game/Order.java @@ -10,6 +10,7 @@ public class Order implements Disposable, Pool.Poolable, Comparable<Unit> public static int orderId = 1; public static final Order END = new Order(OrderType.END); + public static final Order REVERT = new Order(OrderType.REVERT); public enum OrderType { @@ -18,6 +19,7 @@ public class Order implements Disposable, Pool.Poolable, Comparable<Unit> ENGAGE, PROMOTE, END, + REVERT, } private static final Pool<Order> orderPool = new Pool<Order>() @@ -64,6 +66,8 @@ public class Order implements Disposable, Pool.Poolable, Comparable<Unit> @Override public void dispose() { + if ((type == OrderType.END) || (type == OrderType.REVERT)) + throw new RuntimeException(String.format("call dispose() on a static Order %s", type)); orderPool.free(this); } @@ -102,32 +106,44 @@ public class Order implements Disposable, Pool.Poolable, Comparable<Unit> @Override public String toString() { - if (type == OrderType.END) - return String.format("[00] END"); - else - return String.format("[%d] %s(%d) : %s", id, type, cost, leader.code); + switch (type) + { + case END: + return String.format("[00] END"); + case REVERT: + return String.format("%s[%d]", type, id); + default: + return String.format("[%d] %s(%d) : %s", id, type, cost, leader.code); + } } public void setMove(Unit unit, Move move) { - this.leader = unit; this.type = OrderType.MOVE; + this.leader = unit; this.move = move; } public void setPromote(Unit unit) { - this.leader = unit; this.type = OrderType.PROMOTE; + this.leader = unit; } public void setEngage(Unit unit, Unit target) { - this.leader = unit; this.type = OrderType.ENGAGE; + this.leader = unit; this.engagement = Engagement.get(unit, target); } + public void setRevert(int id) + { + this.type = OrderType.REVERT; + this.id = id; + this.cost = 0; + } + public void setActivables(UnitList l) { for(Unit u : l) diff --git a/core/src/ch/asynk/rustanddust/game/Player.java b/core/src/ch/asynk/rustanddust/game/Player.java index c5d3473..0018e1a 100644 --- a/core/src/ch/asynk/rustanddust/game/Player.java +++ b/core/src/ch/asynk/rustanddust/game/Player.java @@ -193,12 +193,12 @@ public class Player public void turnEnd() { apSpent = ap; - for (Unit unit : units) - unit.reset(); } public void turnStart(int aps) { + for (Unit unit : units) + unit.reset(); if (isDeploymentDone()) { ap = aps; apSpent = 0; diff --git a/core/src/ch/asynk/rustanddust/game/State.java b/core/src/ch/asynk/rustanddust/game/State.java index a3a6fec..9ab1576 100644 --- a/core/src/ch/asynk/rustanddust/game/State.java +++ b/core/src/ch/asynk/rustanddust/game/State.java @@ -1,32 +1,25 @@ package ch.asynk.rustanddust.game; +import ch.asynk.rustanddust.game.Ctrl.MsgType; + public interface State { - enum StateType { - LOADING, + enum StateType + { REPLAY, + WAIT_EVENT, SELECT, MOVE, - ROTATE, ENGAGE, - BREAK, PROMOTE, ANIMATION, REINFORCEMENT, DEPLOYMENT, - WITHDRAW, - ABORT, - DONE, - TURN_OVER }; - public void enterFrom(StateType prevState); - - public void leaveFor(StateType nextState); - - public StateType abort(); + public void touch(Hex hex); - public StateType execute(); + public void enterFrom(StateType prevState); - public void touch(Hex hex); + public boolean processMsg(MsgType msg, Object data); } diff --git a/core/src/ch/asynk/rustanddust/game/Unit.java b/core/src/ch/asynk/rustanddust/game/Unit.java index 7a9f2e2..4dd04ee 100644 --- a/core/src/ch/asynk/rustanddust/game/Unit.java +++ b/core/src/ch/asynk/rustanddust/game/Unit.java @@ -315,7 +315,7 @@ public class Unit extends HeadedPawn if (cost > mpLeft) RustAndDust.debug("ERROR: Movement point exceeded: " + cost + "/" + mpLeft + " please report"); - if ((cost > 0) && move.isFinal()) + if (cost > 0) setMoved(); spendMovementPoints(cost); diff --git a/core/src/ch/asynk/rustanddust/game/battles/BattleCommon.java b/core/src/ch/asynk/rustanddust/game/battles/BattleCommon.java index e7bcac5..a70698b 100644 --- a/core/src/ch/asynk/rustanddust/game/battles/BattleCommon.java +++ b/core/src/ch/asynk/rustanddust/game/battles/BattleCommon.java @@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.JsonValue; import ch.asynk.rustanddust.util.Marshal; +import ch.asynk.rustanddust.game.Ctrl; import ch.asynk.rustanddust.game.Battle; import ch.asynk.rustanddust.game.Player; import ch.asynk.rustanddust.game.State; @@ -13,6 +14,7 @@ import ch.asynk.rustanddust.game.Map; import ch.asynk.rustanddust.game.Zone; import ch.asynk.rustanddust.game.Unit; import ch.asynk.rustanddust.game.Unit.UnitCode; +import ch.asynk.rustanddust.game.Order; import ch.asynk.rustanddust.game.Factory; import ch.asynk.rustanddust.game.State.StateType; import ch.asynk.rustanddust.engine.Orientation; @@ -21,6 +23,7 @@ public abstract class BattleCommon implements Battle { protected final static Random random = new Random(System.currentTimeMillis()); + private Ctrl ctrl; protected final Factory factory; protected int _id; @@ -67,12 +70,14 @@ public abstract class BattleCommon implements Battle @Override public Factory.MapType getMapType() { return mapType; } @Override - public void init() + public Map init(Ctrl ctrl) { + this.ctrl = ctrl; this.map = factory.getMap(getMapType()); setup(); this.turnCount = 0; this.currentPlayer = players[0]; + return this.map; } @Override @@ -90,52 +95,49 @@ public abstract class BattleCommon implements Battle { this.currentPlayer = players[0]; deployPlayer(); - currentPlayer.turnEnd(); this.currentPlayer = players[1]; deployPlayer(); - currentPlayer.turnEnd(); this.currentPlayer = players[0]; - map.turnDone(); } public void load(Marshal.Mode mode, JsonValue value) { - map.load(mode, value); - if((mode == Marshal.Mode.FULL) || (mode == Marshal.Mode.STATE)) { - JsonValue v = value.get("battle"); - this.turnCount = v.getInt("turnCount"); + if (mode == Marshal.Mode.PLAYERS) { map.loadPlayers(value, players); + this.currentPlayer = players[0]; + } else { + if (mode == Marshal.Mode.MAP) { + JsonValue v = value.get("battle"); + this.turnCount = v.getInt("turnCount"); + Unit.unitId = v.getInt("unitId"); + Order.orderId = v.getInt("orderId"); + } + map.load(mode, value); } - this.currentPlayer = players[0]; } @Override public void unload(Marshal.Mode mode, Json json) { json.writeObjectStart(); - if((mode == Marshal.Mode.FULL) || (mode == Marshal.Mode.STATE)) { - json.writeObjectStart("battle"); - json.writeValue("turnCount", turnCount); - json.writeObjectEnd(); + if (mode == Marshal.Mode.PLAYERS) map.unloadPlayers(json, getPlayer(), getOpponent()); + else { + if (mode == Marshal.Mode.MAP) { + json.writeObjectStart("battle"); + json.writeValue("turnCount", this.turnCount); + json.writeValue("unitId", Unit.unitId); + json.writeValue("orderId", Order.orderId); + json.writeObjectEnd(); + } + map.unload(mode, json); } - map.unload(mode, json); json.writeObjectEnd(); } @Override - public boolean actionDone() - { - boolean burn = (map.unitsActivatedSize() > 0); - if (burn) - currentPlayer.burnDownOneAp(); - map.actionDone(); - return burn; - } - - @Override public boolean turnDone() { boolean ret = false; @@ -150,7 +152,7 @@ public abstract class BattleCommon implements Battle } turnCount += 1; setNextTurn(); - map.turnDone(); + map.clear(); return ret; } @@ -260,7 +262,7 @@ public abstract class BattleCommon implements Battle { Unit unit = factory.getUnit(unitCode, hq, ace); if (exitZone != null) unit.exitZone = exitZone; - map.setOnBoard(unit, map.getHex(col, row), orientation); + ctrl.postInitOrder(map.getSetOrder(unit, map.getHex(col, row), orientation)); return unit; } } diff --git a/core/src/ch/asynk/rustanddust/game/ctrl/Solo.java b/core/src/ch/asynk/rustanddust/game/ctrl/Solo.java index 54d2310..29a8755 100644 --- a/core/src/ch/asynk/rustanddust/game/ctrl/Solo.java +++ b/core/src/ch/asynk/rustanddust/game/ctrl/Solo.java @@ -7,8 +7,6 @@ import ch.asynk.rustanddust.game.Ctrl; public class Solo extends Ctrl { - private int gameId; - public Solo(final RustAndDust game) { super(game); @@ -17,8 +15,8 @@ public class Solo extends Ctrl @Override public void init() { - gameId = game.config.gameId; - if (gameId == game.db.NO_RECORD) { + GameRecord r = loadState(); + if (r == null) { int me = game.backend.getMyId(); int other = game.backend.getOpponentId(); gameId = game.db.storeGameGetId(other, battle.getId(), game.config.gameMode.i); @@ -27,68 +25,28 @@ public class Solo extends Ctrl battle.initialDeployment(); synched = true; } else { - GameRecord r = loadState(); - if (r != null) { - load(Marshal.Mode.STATE, r.state); - load(Marshal.Mode.ORDERS, r.orders); - battle.getMap().clearMarshalUnits(); - synched = r.synched; - r.dispose(); - } else - System.err.println("TODO : null GameRecord"); + load(Marshal.Mode.MAP, r.map); + load(Marshal.Mode.PLAYERS, r.players); + load(Marshal.Mode.ORDERS, r.orders); + battle.getMap().clearMarshalUnits(); + synched = r.synched; + r.dispose(); } } private GameRecord loadState() { GameRecord r = null; - switch (game.config.loadMode) { - case LOAD: - r = game.db.loadGame(gameId); - break; - case REPLAY_LAST: - r = game.db.loadLastTurn(gameId); - break; + gameId = game.config.gameId; + switch (game.config.loadMode) + { + case NEW: break; + case RESUME: r = game.db.loadGame(gameId); break; + case REPLAY_CURRENT: r = game.db.loadLastTurn(gameId); break; case REPLAY_ALL: // TODO REPLAY_ALL break; } return r; } - - @Override - public void orderProcessedCb() - { - if (!isLoading()) - storeOrders(); - } - - @Override - protected void actionDoneCb() - { - storeState(); - } - - @Override - protected void turnDoneCb() - { - storeOrders(); - storeState(); - storeTurn(); - } - - private void storeState() - { - game.db.storeGameState(gameId, battle.getTurnCount(), battle.getPlayer().id, unload(Marshal.Mode.STATE)); - } - - private void storeOrders() - { - game.db.storeGameOrders(gameId, battle.getTurnCount(), battle.getPlayer().id, unload(Marshal.Mode.ORDERS)); - } - - private void storeTurn() - { - game.db.storeLastTurn(gameId); - } } diff --git a/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java b/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java index 90ec017..e992867 100644 --- a/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java +++ b/core/src/ch/asynk/rustanddust/game/hud/ActionButtons.java @@ -6,7 +6,7 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import ch.asynk.rustanddust.RustAndDust; import ch.asynk.rustanddust.game.Ctrl; -import ch.asynk.rustanddust.game.State.StateType; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.ui.Widget; import ch.asynk.rustanddust.ui.Bg; import ch.asynk.rustanddust.ui.Position; @@ -36,7 +36,7 @@ public class ActionButtons extends Widget private Sprite bg; private Bg buttons []; - private StateType states []; + private MsgType msgs []; public ActionButtons(RustAndDust game) { @@ -50,10 +50,10 @@ public class ActionButtons extends Widget this.buttons[Buttons.ABORT.i] = new Bg(game.factory.getHudRegion(game.factory.ACT_ABORT)); this.buttons[Buttons.PROMOTE.i] = new Bg(game.factory.getHudRegion(game.factory.ACT_PROMOTE)); - this.states = new StateType[Buttons.LAST.i]; - this.states[Buttons.DONE.i] = StateType.DONE; - this.states[Buttons.ABORT.i] = StateType.ABORT; - this.states[Buttons.PROMOTE.i] = StateType.PROMOTE; + this.msgs = new MsgType[Buttons.LAST.i]; + this.msgs[Buttons.DONE.i] = MsgType.OK; + this.msgs[Buttons.ABORT.i] = MsgType.CANCEL; + this.msgs[Buttons.PROMOTE.i] = MsgType.PROMOTE; } @Override @@ -135,7 +135,7 @@ public class ActionButtons extends Widget for (int i = 0; i < Buttons.LAST.i; i++) { if (buttons[i].hit(x, y)) { - ctrl.post(states[i]); + ctrl.sendMsg(msgs[i]); return true; } } diff --git a/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java b/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java index e96856f..9f86b13 100644 --- a/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java +++ b/core/src/ch/asynk/rustanddust/game/hud/PlayerInfo.java @@ -141,12 +141,12 @@ public class PlayerInfo implements Disposable, Drawable, Animation return true; } else if (reinforcement.hit(x, y)) { - ctrl.postEvent(Ctrl.EventType.UNIT_DOCK_TOGGLE); + ctrl.sendMsg(Ctrl.MsgType.UNIT_DOCK_TOGGLE); return true; } else if (unitDock.hit(x, y)) { - ctrl.hud.notify(unitDock.selectedUnit.toString(), Position.TOP_CENTER); - ctrl.postEvent(Ctrl.EventType.UNIT_DOCK_SELECT, unitDock.selectedUnit); + ctrl.hud.notify(unitDock.selectedUnit.toString()); + ctrl.sendMsg(Ctrl.MsgType.UNIT_DOCK_SELECT, unitDock.selectedUnit); return true; } diff --git a/core/src/ch/asynk/rustanddust/game/map/Map1Units.java b/core/src/ch/asynk/rustanddust/game/map/Map1Units.java index 3aa0c8d..b490042 100644 --- a/core/src/ch/asynk/rustanddust/game/map/Map1Units.java +++ b/core/src/ch/asynk/rustanddust/game/map/Map1Units.java @@ -79,13 +79,13 @@ public abstract class Map1Units extends Map0Hex } } - public Unit unitsMoveableGet(int i) { return activableUnits.get(i); } + public Unit getFirstActivable() { return activableUnits.get(0); } public void unitsTargetClear() { targetUnits.clear(); } public void unitsActivatedClear() { activatedUnits.clear(); } public int unitsActivatedSize() { return activatedUnits.size(); } - public int unitsActivableSize() { return activableUnits.size(); } + public int unitsActivableSize() { return activableUnits.size(); } public boolean unitsTargetContains(Unit unit) { return targetUnits.contains(unit); } public boolean unitsActivableContains(Unit unit) { return activableUnits.contains(unit); } @@ -94,8 +94,8 @@ public abstract class Map1Units extends Map0Hex public void unitsTargetHide() { unitsShowOverlay(targetUnits, Unit.TARGET, false); } public void unitsAssistShow() { unitsShowOverlay(activableUnits, Unit.MAY_FIRE, true); } public void unitsAssistHide() { unitsShowOverlay(activableUnits, Unit.MAY_FIRE, false); unitsShowOverlay(activableUnits, Unit.FIRE, false); } - public void unitsActivableShow() { unitsShowOverlay(activableUnits, Unit.ACTIVEABLE, true); } - public void unitsActivableHide() { unitsShowOverlay(activableUnits, Unit.ACTIVEABLE, false); } + public void unitsActivableShow() { unitsShowOverlay(activableUnits, Unit.ACTIVEABLE, true); } + public void unitsActivableHide() { unitsShowOverlay(activableUnits, Unit.ACTIVEABLE, false); } private void unitsShowOverlay(UnitList units, int overlay, boolean on) { diff --git a/core/src/ch/asynk/rustanddust/game/map/Map2Moves.java b/core/src/ch/asynk/rustanddust/game/map/Map2Moves.java index e7ba8ce..e092fea 100644 --- a/core/src/ch/asynk/rustanddust/game/map/Map2Moves.java +++ b/core/src/ch/asynk/rustanddust/game/map/Map2Moves.java @@ -51,21 +51,10 @@ public abstract class Map2Moves extends Map1Units return 0; } - public void collectUpdate(Unit unit) - { - movesHide(); - unitsActivableHide(); - movesCollect(unit); - collectMoveable(unit); - movesShow(); - unitsActivableShow(); - activatedUnits.clear(); - } - public int pathsSize() { return paths.size(); } public void pathsClear() { paths.clear(); } public void pathsInit(Unit unit) { paths.init(unit); } - public void pathsInit(Unit unit, Hex hex) { paths.init(unit, hex); } + public void pathsInit(Unit unit, Hex from) { paths.init(unit, from); } public int pathsBuild(Hex hex) { return paths.build(hex); } public Hex pathsTo() { return (Hex) paths.to; } public void pathsSetOrientation(Orientation o) { paths.orientation = o; } diff --git a/core/src/ch/asynk/rustanddust/game/map/Map3Animations.java b/core/src/ch/asynk/rustanddust/game/map/Map3Animations.java index eba741b..d109366 100644 --- a/core/src/ch/asynk/rustanddust/game/map/Map3Animations.java +++ b/core/src/ch/asynk/rustanddust/game/map/Map3Animations.java @@ -4,6 +4,7 @@ import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.Texture; import ch.asynk.rustanddust.RustAndDust; +import ch.asynk.rustanddust.engine.Move; import ch.asynk.rustanddust.engine.SelectedTile; import ch.asynk.rustanddust.engine.gfx.Moveable; import ch.asynk.rustanddust.engine.gfx.animations.AnimationSequence; @@ -21,7 +22,7 @@ import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Unit; import ch.asynk.rustanddust.game.Army; import ch.asynk.rustanddust.game.Player; -import ch.asynk.rustanddust.game.Ctrl.EventType; +import ch.asynk.rustanddust.game.Ctrl.MsgType; public abstract class Map3Animations extends Map2Moves implements MoveToAnimationCb { @@ -31,6 +32,8 @@ public abstract class Map3Animations extends Map2Moves implements MoveToAnimatio private Sound sound; private long soundId = -1; + protected static final float BOUNCE_DURATION = 0.3f; + public Map3Animations(final RustAndDust game, Texture map, SelectedTile hex) { super(game, map, hex); @@ -92,18 +95,50 @@ public abstract class Map3Animations extends Map2Moves implements MoveToAnimatio // <- implement MoveToAnimationCb - protected void addBounceAnimation(final Unit unit, float duration) + protected void moveUnit(final Unit unit, final Move move, MoveToAnimationCb cb, boolean bounce) { - addAnimation(BounceAnimation.get(unit, duration)); + removePawn(unit); + + AnimationSequence seq = AnimationSequence.get(move.steps() + (bounce ? 2 : 1)); + if (bounce) seq.addAnimation(BounceAnimation.get(unit, BOUNCE_DURATION)); + unit.getMoveAnimation(move.iterator(), seq, cb); + seq.addAnimation(RunnableAnimation.get(unit, new Runnable() { + @Override + public void run() { + unit.move(move); + if (!move.to.isOffMap()) + setPawnOnto(unit, move.to, move.orientation); + } + })); + addAnimation(seq); } - protected void addPromoteAnimation(final Unit unit, final Player player, final Runnable after) + protected void revertLastUnitMove(final Unit unit, final Move move) { - Hex hex = unit.getHex(); - AnimationSequence seq = AnimationSequence.get(2); - seq.addAnimation(PromoteAnimation.get((unit.getArmy() == Army.US), hex.getX(), hex.getY(), game.config.fxVolume)); - seq.addAnimation(RunnableAnimation.get(unit, after)); + removePawn(unit); + revertClaim(unit, move); + + AnimationSequence seq = AnimationSequence.get(1); + unit.getRevertLastMoveAnimation(seq); + seq.addAnimation(RunnableAnimation.get(unit, new Runnable() { + @Override + public void run() { + setPawnOnto(unit, move.to, move.orientation); + } + })); addAnimation(seq); + unit.revertLastMove(); + } + + protected void addBounceAnimation(final Unit unit) + { + addAnimation(BounceAnimation.get(unit, BOUNCE_DURATION)); + } + + protected void addPromoteAnimation(final Unit unit, final Player player) + { + Hex hex = unit.getHex(); + addAnimation(PromoteAnimation.get((unit.getArmy() == Army.US), hex.getX(), hex.getY(), game.config.fxVolume)); } protected void addDestroyAnimation(Unit unit) @@ -142,6 +177,6 @@ public abstract class Map3Animations extends Map2Moves implements MoveToAnimatio addAnimation( SoundAnimation.get(SoundAnimation.Action.FADE_OUT, sound, soundId, game.config.fxVolume, 0.5f)); soundId = -1; } else - game.ctrl.postEvent(EventType.ANIMATIONS_DONE); + game.ctrl.sendMsg(MsgType.ANIMATIONS_DONE); } } diff --git a/core/src/ch/asynk/rustanddust/game/map/Map4Orders.java b/core/src/ch/asynk/rustanddust/game/map/Map4Orders.java index e3662e2..05cc569 100644 --- a/core/src/ch/asynk/rustanddust/game/map/Map4Orders.java +++ b/core/src/ch/asynk/rustanddust/game/map/Map4Orders.java @@ -6,8 +6,10 @@ import ch.asynk.rustanddust.RustAndDust; import ch.asynk.rustanddust.engine.Move; import ch.asynk.rustanddust.engine.SelectedTile; import ch.asynk.rustanddust.engine.Orientation; -import ch.asynk.rustanddust.game.Hex; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.game.Unit; +import ch.asynk.rustanddust.game.Hex; +import ch.asynk.rustanddust.game.Zone; import ch.asynk.rustanddust.game.Order; import ch.asynk.rustanddust.game.OrderList; import ch.asynk.rustanddust.game.Engagement; @@ -17,15 +19,12 @@ public abstract class Map4Orders extends Map3Animations protected final OrderList orders; protected final OrderList replayOrders; - protected int orderId; - protected abstract int engagementCost(Engagement e); protected abstract void resolveEngagement(Engagement e); public Map4Orders(final RustAndDust game, Texture map, SelectedTile hex) { super(game, map, hex); - this.orderId = 0; this.orders = new OrderList(10); this.replayOrders = new OrderList(10); } @@ -39,78 +38,126 @@ public abstract class Map4Orders extends Map3Animations Engagement.clearPool(); } - protected void incOrderId() { orderId += 1; } protected int ordersSize() { return orders.size(); } protected void ordersClear() { orders.dispose(); } // STATES ENTRY -> - public void showOnBoard(final Unit unit, Hex to, Orientation o) + public void setOnBoard(final Unit unit, Move move) { - setPawnOnto(unit, to, o); + setPawnOnto(unit, move); + addBounceAnimation(unit); } - public boolean setOnBoard(final Unit unit, Hex to, Orientation entry) + public void setOnBoard(final Unit unit, Hex to, Orientation o) { - orders.dispose(unit); - return process(getMoveOrder(unit, Move.getSet(unit, to, entry))); + setPawnOnto(unit, to, o); + addBounceAnimation(unit); } - public boolean enterBoard(final Unit unit, Hex to, int allowedMoves) + public boolean enterBoard(final Unit unit, Hex to, Zone entryZone) { - Orientation entry = findBestEntry(unit, to, allowedMoves); + Orientation entry = findBestEntry(unit, to, entryZone.allowedMoves); if (entry == Orientation.KEEP) return false; - - return process(getMoveOrder(unit, Move.getEnter(unit, to, entry))); + unit.spendMovementPoints(to.costFrom(unit, entry)); + setOnBoard(unit, to, entry.opposite()); + return true; } - public boolean exitBoard(final Unit unit) + public void revertEnter(final Unit unit) { - return process(getMoveOrder(unit, paths.getExitMove())); + removePawn(unit); + unit.reset(); } - public boolean moveUnit(final Unit unit) + public Order getSetOrder(final Unit unit, final Hex to, final Orientation o) { - return process(getMoveOrder(unit, paths.getMove())); + Order order = getMoveOrder(unit, Move.getSet(unit, to, o), false); + order.cost = 0; + + return order; } - public void revertMoves() + public Order getRevertSetOrder(Unit unit) { - for (Unit unit: activatedUnits) { - RustAndDust.debug(" revertMove() " + unit); - revertLastPawnMove(unit, ((Order) orders.get(unit, Order.OrderType.MOVE)).move); - orders.dispose(unit, Order.OrderType.MOVE); + Order o = orders.get(unit, Order.OrderType.MOVE); + if (o == null) { + RustAndDust.error(String.format("can't revert order : %s %s", Order.OrderType.MOVE, unit)); + return null; } - activatedUnits.clear(); + Order order = Order.REVERT; + order.setRevert(o.id); + + return order; } - public void revertEnter(final Unit unit) + public Order getExitOrder(final Unit unit, boolean hqMode) { - RustAndDust.debug(" revertEnter() "+ unit); + Order order = getMoveOrder(unit, paths.getExitMove(), hqMode); - revertclaim(unit, unit.getHex()); - removePawn(unit); - game.ctrl.battle.getPlayer().revertUnitEntry(unit); - orders.dispose(unit); - unit.reset(); + return order; } - public boolean engageUnit(final Unit unit, final Unit target) + public Order getEnterOrder(final Unit unit, boolean hqMode) { - attack(unit, target, true); + Order order = getMoveOrder(unit, paths.getEnterMove(unit, getAdjTileAt(unit.getTile(), unit.getOrientation().opposite())), hqMode); + + return order; + } + + public Order getMoveOrder(final Unit unit, boolean hqMode) + { + Order order = getMoveOrder(unit, paths.getMove(), hqMode); + return order; + } + + // FIXME revertMoves(...) + // public void revertMoves() + // { + // for (Unit unit: activatedUnits) { + // RustAndDust.debug(" revertMove() " + unit); + // revertLastPawnMove(unit, ((Order) orders.get(unit, Order.OrderType.MOVE)).move); + // orders.dispose(unit, Order.OrderType.MOVE); + // } + // activatedUnits.clear(); + // } + + public Order getEngageOrder(final Unit unit, final Unit target) + { + attack(unit, target, true); Order order = Order.get(); order.setEngage(unit, target); - process(order); - return order.engagement.success; + + Engagement e = order.engagement; + resolveEngagement(e); + order.setActivables(activableUnits); + if ((e.cost > 0) && order.activables.size() > 0) + order.cost = 0; + + return order; } - public boolean promoteUnit(final Unit unit) + public Order getPromoteOrder(final Unit unit) { Order order = Order.get(); order.setPromote(unit); - return process(order); + + return order; + } + + private Order getMoveOrder(Unit leader, Move move, boolean hqMode) + { + Order order = Order.get(); + order.setMove(leader, move); + activableUnits.remove((Unit) move.pawn); + activatedUnits.add((Unit) move.pawn); + order.setActivables(activableUnits); + if (hqMode && order.activables.size() > 0) + order.cost = 0; + + return order; } // STATES ENTRY <- @@ -120,22 +167,36 @@ public abstract class Map4Orders extends Map3Animations public void prepareReplayLastAction() { int s = orders.size(); - int a = orders.get(s - 1).id; - while (s > 0) { + if (s == 0) return; + + boolean more = true; + // int a = orders.get(s - 1).id; + while (more) { s -= 1; Order o = orders.get(s); - if (o.id != a) - break; + o.replay = true; replayOrders.add(o); + if (s == 0) { + more = false; + } else { + Order prev = orders.get(s - 1); + // first order cost=1 part of a group action + if ((o.cost > 0) && (s > 0) && replayOrders.size() == 1) + more = ((prev.cost == 0) && (prev.type == o.type)); + else // part of a group action + more = ((o.cost == 0) && (prev.cost == 0) && (prev.type == o.type)); + } } } - public void prepareReplayLastTurn() + public void prepareReplayCurrentTurn() { int s = orders.size(); while (s > 0) { s -= 1; - replayOrders.add(orders.get(s)); + Order o = orders.get(s); + o.replay = true; + replayOrders.add(o); } } @@ -147,154 +208,129 @@ public abstract class Map4Orders extends Map3Animations return replayOrders.remove(s - 1); } - public boolean replay(Order order) - { - return process(order, true); - } - // REPLAY <- - private Order getMoveOrder(Unit unit, Move move) + // EXECUTE -> + + public void execute(final Order order) { - Order order = Order.get(); - order.setMove(unit, move); - return order; + RustAndDust.debug(" Order", order.toString()); + + switch(order.type) + { + case MOVE: executeMove(order); break; + case ENGAGE: executeEngage(order); break; + case PROMOTE: executePromote(order); break; + case END: executeEnd(order); return; + case REVERT: executeRevert(order); return; + default: + RustAndDust.error(String.format("Unhandled Order Type %s", order.type)); + break; + } + + if (order.replay) { + activableUnits.clear(); + for (Unit u : order.activables) + activableUnits.add(u); + } else + orders.add(order); } - private boolean process(Order order) + private void executePromote(final Order order) { - return process(order, false); + addPromoteAnimation(order.leader, game.ctrl.battle.getPlayer()); } - private boolean process(Order order, boolean replay) + private void executeEngage(final Order order) { - RustAndDust.debug("Order", order.toString()); + Engagement e = order.engagement; - boolean r = false; + e.attacker.engage(); + for (Unit u : e.assists) + u.engage(); - switch(order.type) { - case MOVE: - r = doMove(order.unit, order.move, replay); - break; - case PROMOTE: - r = doPromote(order.unit, replay); - break; - case ENGAGE: - r = doEngagement(order.engagement, replay); - break; - default: - RustAndDust.error(String.format("Unhandled Order Type %s", order.type)); - break; - } - - if (r && !replay) { - order.id = orderId; - order.setActivable(activableUnits); - order.cost = ((activatedUnits.size() > 0) ? ((activableUnits.size() > 0) ? 0 : 1) : 0); - orders.add(order); - game.ctrl.orderProcessedCb(); + if (order.replay) { + activatedUnits.clear(); + activatedUnits.add(e.attacker); + addBounceAnimation(e.attacker); + for (Unit u : e.assists) { + activatedUnits.add(u); + addBounceAnimation(u); + } } - if (replay) { - activableUnits.clear(); - for (Unit u : order.activable) - activableUnits.add(u); - orderId = order.id; + if (e.success) { + unclaim(e.defender, e.defender.getHex()); + removePawn(e.defender); + addDestroyAnimation(e.defender); } - - return r; + addEngagementAnimation(e.defender); } - private boolean doMove(Unit unit, Move move, boolean replay) + private void executeMove(final Order order) { - RustAndDust.debug(" Move", String.format("%s %s", move.type, move.toString())); + final Unit leader = order.leader; + final Unit unit = (Unit) order.move.pawn; + final Move move = order.move; - switch(move.type) { + switch(move.type) + { case REGULAR: - initMove(unit); - movePawn(unit, move, this); - break; - case EXIT: - initMove(unit); - movePawn(unit, move, this); - game.ctrl.battle.getPlayer().unitWithdraw(unit); + playMoveSound(unit); + moveUnit(unit, move, this, order.replay); break; case SET: - setPawnOnto(unit, move); - game.ctrl.battle.getPlayer().unitEntry(unit); claim(unit, move.to); - addBounceAnimation(unit, 0.3f); + if (!order.replay) + orders.dispose(unit, Order.OrderType.MOVE); + setOnBoard(unit, move); break; case ENTER: - enterPawn(unit, move); - game.ctrl.battle.getPlayer().unitEntry(unit); - claim(unit, move.to); - addBounceAnimation(unit, 0.3f); + claim(unit, move.from); + if (order.replay) + unit.setOnTile(move.from, Orientation.NORTH.r()); + playMoveSound(unit); + moveUnit(unit, move, this, order.replay); + break; + case EXIT: + playMoveSound(unit); + moveUnit(unit, move, this, order.replay); break; default: - RustAndDust.error(String.format("Unhandled Move Type %s", move.type)); - return false; + RustAndDust.error(String.format("Unhandled Move Type %s", order.move.type)); } - - return true; - } - - private void initMove(Unit unit) - { - activableUnits.remove(unit); - activatedUnits.add(unit); - playMoveSound(unit); } - private boolean doPromote(final Unit unit, boolean replay) + private void executeRevert(Order order) { - activableUnits.remove(unit); - activatedUnits.add(unit); - addPromoteAnimation(unit, game.ctrl.battle.getPlayer(), new Runnable() { - @Override - public void run() { - game.ctrl.battle.getPlayer().promote(unit); - } - }); - return true; - } + int id = order.id; + order = orders.getId(id); + orders.remove(order); - private boolean doEngagement(Engagement e, boolean replay) - { - if (replay) { - activatedUnits.clear(); - for (Unit u : e.assists) { - u.engage(); - activatedUnits.add(u); - } - e.attacker.engage(); - activatedUnits.add(e.attacker); - } else { - resolveEngagement(e); - activableUnits.clear(); - if (e.success) { - for (Unit u : activatedUnits) { - u.engage(); - if (u.canBreak()) - activableUnits.add(u); - } - } + if (order.type != Order.OrderType.MOVE) { + RustAndDust.error(String.format("Unhandled Revert for Order Type %s", order.type)); + return; } - if (e.success) { - unclaim(e.defender, e.defender.getHex()); - removePawn(e.defender); - addDestroyAnimation(e.defender); + Unit unit = (Unit) order.move.pawn; + switch(order.move.type) + { + case SET: + removePawn(unit); + unclaim(unit, order.move.to); + game.ctrl.sendMsg(MsgType.UNIT_UNDEPLOYED, unit); + break; + case REGULAR: + case EXIT: + case ENTER: + default: + RustAndDust.error(String.format("Unhandled Move Type %s", order.move.type)); } - - if (!replay) - game.ctrl.hud.engagementSummary(e); - addEngagementAnimation(e.defender); - - if (engagementCost(e) == 0) - activatedUnits.clear(); - - return true; + order.dispose(); } + private void executeEnd(Order order) + { + orders.get(orders.size() - 1).cost = 1; + } } diff --git a/core/src/ch/asynk/rustanddust/game/map/Map5Marshal.java b/core/src/ch/asynk/rustanddust/game/map/Map5Marshal.java index 9447c38..b291062 100644 --- a/core/src/ch/asynk/rustanddust/game/map/Map5Marshal.java +++ b/core/src/ch/asynk/rustanddust/game/map/Map5Marshal.java @@ -37,10 +37,11 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal @Override public void unload(Marshal.Mode mode, Json json) { - if((mode == Marshal.Mode.FULL) || (mode == Marshal.Mode.STATE)) - unloadMap(json); - else if(mode == Marshal.Mode.ORDERS) - unloadOrders(json, orders); + switch(mode) + { + case MAP: unloadMap(json); break; + case ORDERS: unloadOrders(json, orders); break; + } } public void unloadPlayers(Json json, Player a, Player b) @@ -160,20 +161,15 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal json.writeValue("id", o.id); json.writeValue("type", o.type); json.writeValue("cost", o.cost); - switch(o.type) { - case MOVE: - unloadMoveOrder(json, o.move); - break; - case ENGAGE: - unloadEngageOrder(json, o.engagement); - break; - case PROMOTE: - unloadPromoteOrder(json, o.unit); - break; + switch(o.type) + { + case MOVE: unloadMoveOrder(json, o.leader, o.move); break; + case ENGAGE: unloadEngageOrder(json, o.engagement); break; + case PROMOTE: unloadPromoteOrder(json, o.leader); break; } - if (o.activable.size() > 0) { + if (o.activables.size() > 0) { json.writeArrayStart("a"); - for(Unit u : o.activable) + for(Unit u : o.activables) json.writeValue(u.id()); json.writeArrayEnd(); } @@ -182,9 +178,11 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal json.writeArrayEnd(); } - private void unloadMoveOrder(Json json, Move m) + private void unloadMoveOrder(Json json, Unit leader, Move m) { json.writeValue("mType", m.type); + json.writeValue("mCost", m.cost); + json.writeValue("l", leader.id()); json.writeValue("u", ((Unit) m.pawn).id()); if (m.from != null) { json.writeArrayStart("from"); @@ -267,10 +265,10 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal @Override public void load(Marshal.Mode mode, JsonValue v) { - if((mode == Marshal.Mode.FULL) || (mode == Marshal.Mode.STATE)) - loadMap(v.get("map")); - else if(mode == Marshal.Mode.ORDERS) - loadOrders(v.get("orders")); + switch(mode) { + case MAP: loadMap(v.get("map")); break; + case ORDERS: loadOrders(v.get("orders")); break; + } } public void loadPlayers(JsonValue v, Player[] players) @@ -323,8 +321,7 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal if (pos) { a = v.get("p"); Hex h = getHex(a.getInt(0), a.getInt(1)); - u.setRotation(a.getInt(2)); - showOnBoard(u, h, Orientation.fromRotation(a.getInt(2))); + setOnBoard(u, h, Orientation.fromRotation(a.getInt(2))); } units.add(u); return u; @@ -366,23 +363,18 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal for (int i = 0; i < v.size; i++) { JsonValue o = v.get(i); Order order = null; - switch(Order.OrderType.valueOf(o.getString("type"))) { - case MOVE: - order = loadMoveOrder(o); - break; - case ENGAGE: - order = loadEngageOrder(o); - break; - case PROMOTE: - order = loadPromoteOrder(o); - break; + switch(Order.OrderType.valueOf(o.getString("type"))) + { + case MOVE: order = loadMoveOrder(o); break; + case ENGAGE: order = loadEngageOrder(o); break; + case PROMOTE: order = loadPromoteOrder(o); break; } order.id = o.getInt("id"); order.cost = o.getInt("cost"); JsonValue a = o.get("a"); if (a != null) { for (int j = 0; j < a.size; j++) { - order.activable.add(findById(a.getInt(j))); + order.activables.add(findById(a.getInt(j))); } } orders.add(order); @@ -391,6 +383,7 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal private Order loadMoveOrder(JsonValue v) { + Unit leader = findById(v.getInt("l")); Unit unit = findById(v.getInt("u")); if (unit == null) return null; Hex from = loadHex(v, "from"); @@ -408,24 +401,20 @@ public abstract class Map5Marshal extends Map4Orders implements Marshal } Move m = null; - switch(Move.MoveType.valueOf(v.getString("mType"))) { - case REGULAR: - m = Move.get(unit, from, to, orientation, path); - break; - case ENTER: - m = Move.getEnter(unit, to, orientation); - break; - case SET: - m = Move.getSet(unit, to, orientation); - break; + switch(Move.MoveType.valueOf(v.getString("mType"))) + { + case REGULAR: m = Move.get(unit, from, to, orientation, path); break; + case ENTER: m = Move.getEnter(unit, from, to, orientation, path); break; + case SET: m = Move.getSet(unit, to, orientation); break; case EXIT: m = Move.get(unit, from, to, orientation, path); m.type = Move.MoveType.EXIT; break; } + m.cost = v.getInt("mCost"); Order o = Order.get(); - o.setMove(unit, m); + o.setMove(leader, m); return o; } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateAnimation.java b/core/src/ch/asynk/rustanddust/game/states/StateAnimation.java index c19f16b..4c6a965 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateAnimation.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateAnimation.java @@ -5,23 +5,7 @@ public class StateAnimation extends StateCommon @Override public void enterFrom(StateType prevState) { + ctrl.blockMap = true; ctrl.hud.actionButtons.hide(); } - - @Override - public void leaveFor(StateType nextState) - { - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateBreak.java b/core/src/ch/asynk/rustanddust/game/states/StateBreak.java deleted file mode 100644 index 1dab40b..0000000 --- a/core/src/ch/asynk/rustanddust/game/states/StateBreak.java +++ /dev/null @@ -1,76 +0,0 @@ -package ch.asynk.rustanddust.game.states; - -import ch.asynk.rustanddust.engine.Orientation; -import ch.asynk.rustanddust.game.Hex; -import ch.asynk.rustanddust.game.Unit; -import ch.asynk.rustanddust.game.hud.ActionButtons.Buttons; - -public class StateBreak extends StateCommon -{ - private Orientation o = Orientation.KEEP; - - @Override - public void enterFrom(StateType prevState) - { - activeUnit = null; - ctrl.hud.actionButtons.show(Buttons.DONE.b); - ctrl.hud.notify("Break Through possible"); - map.unitsActivableShow(); - } - - @Override - public void leaveFor(StateType nextState) - { - map.unitsActivableHide(); - map.hexMoveHide(to); - map.hexDirectionsHide(to); - if (activeUnit != null) map.hexMoveHide(activeUnit.getHex()); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; - } - - @Override - public void touch(Hex hex) - { - // TODO : cancel preview move before showing rotation - if (activeUnit == null) { - Unit unit = hex.getUnit(); - if (map.unitsActivableContains(unit)) { - activeUnit = unit; - map.hexMoveShow(hex); - map.hexMoveShow(to); - map.hexDirectionsShow(to); - map.unitsActivableHide(); - } - } else { - o = Orientation.fromAdj(to, hex); - - if (o == Orientation.KEEP) return; - - doRotation(o); - ctrl.post(StateType.ANIMATION); - } - } - - private void doRotation(Orientation o) - { - if (activeUnit == null) return; - - map.pathsInit(activeUnit); - map.pathsBuild(to); - map.pathsChooseShortest(); - map.pathsSetOrientation(o); - map.moveUnit(activeUnit); - ctrl.setAfterAnimationState(StateType.DONE); - } -} diff --git a/core/src/ch/asynk/rustanddust/game/states/StateCommon.java b/core/src/ch/asynk/rustanddust/game/states/StateCommon.java index b894c0f..1614465 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateCommon.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateCommon.java @@ -1,12 +1,13 @@ package ch.asynk.rustanddust.game.states; +import ch.asynk.rustanddust.RustAndDust; import ch.asynk.rustanddust.game.Map; import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Unit; import ch.asynk.rustanddust.game.Ctrl; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.game.State; import ch.asynk.rustanddust.game.Config; -import ch.asynk.rustanddust.RustAndDust; public abstract class StateCommon implements State { @@ -17,7 +18,6 @@ public abstract class StateCommon implements State protected static Hex selectedHex = null; protected static Hex to = null; - protected boolean isEnemy; protected static Unit activeUnit; protected static Unit selectedUnit; @@ -28,26 +28,12 @@ public abstract class StateCommon implements State map = game.ctrl.map; } - protected boolean hasUnit() - { - return (selectedUnit != null); - } - - protected void showPossibilities(Unit unit) - { - if (cfg.showMoves && unit.canMove()) map.movesShow(); - if (cfg.showTargets && unit.canEngage()) map.unitsTargetShow(); - if (cfg.showMoveAssists && unit.canMove()) map.unitsActivableShow(); - unit.hideActiveable(); - } + @Override + public void touch(Hex hex) { } - protected void hidePossibilities() + @Override + public boolean processMsg(MsgType state, Object data) { - map.movesHide(); - map.unitsTargetHide(); - map.unitsActivableHide(); + return false; } - - @Override - public void touch(Hex hex) { } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateDeployment.java b/core/src/ch/asynk/rustanddust/game/states/StateDeployment.java index f967917..27ed7b8 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateDeployment.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateDeployment.java @@ -5,6 +5,7 @@ import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Zone; import ch.asynk.rustanddust.game.Unit; import ch.asynk.rustanddust.game.UnitList; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.game.hud.ActionButtons.Buttons; public class StateDeployment extends StateCommon @@ -15,55 +16,48 @@ public class StateDeployment extends StateCommon @Override public void enterFrom(StateType prevState) { - if (selectedHex != null) - map.hexUnselect(selectedHex); - entryZone = null; - selectedHex = null; - selectedUnit = null; - ctrl.hud.actionButtons.hide(); + clear(); ctrl.hud.playerInfo.unitDock.show(); } @Override - public void leaveFor(StateType nextState) - { - selectedUnit = null; - if (selectedHex != null) - map.hexUnselect(selectedHex); - if (entryZone != null) - entryZone.enable(Hex.AREA, false); - ctrl.hud.playerInfo.unitDock.hide(); - } - - @Override - public StateType abort() + public boolean processMsg(MsgType msg, Object data) { - if (activeUnit != null) - undo(); - return StateType.DEPLOYMENT; - } + switch(msg) + { + case UNIT_DOCK_SELECT: + showEntryZone((Unit) data); + return true; + case CANCEL: + if (activeUnit != null) + undeployUnit(); + return true; + case OK: + deployedUnits.clear(); + ctrl.postTurnDone(); + return true; + case UNIT_DEPLOYED: + deployedUnits.add((Unit) data); + return true; + case UNIT_UNDEPLOYED: + ctrl.battle.getPlayer().revertUnitEntry((Unit) data); + return true; + } - @Override - public StateType execute() - { - deployedUnits.clear(); - return StateType.DONE; + return false; } @Override public void touch(Hex hex) { - Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; - if (hex == null) { - showEntryZone(unit); - } else if (selectedUnit != null) { + if (activeUnit != null) { deployUnit(Orientation.fromAdj(selectedHex, hex)); - } else if (!ctrl.battle.isDeploymentDone() && (entryZone != null) && (hex != null)) { + } else if ((selectedUnit != null) && (entryZone != null)) { if (hex.isEmpty() && entryZone.contains(hex)) { - showUnit(activeUnit, hex); + showUnit(selectedUnit, hex); } } else { - unit = hex.getUnit(); + Unit unit = hex.getUnit(); if (deployedUnits.contains(unit)) showRotation(unit, hex); } @@ -71,28 +65,19 @@ public class StateDeployment extends StateCommon private void showEntryZone(Unit unit) { - activeUnit = unit; - if (entryZone != null) entryZone.enable(Hex.AREA, false); - entryZone = activeUnit.entryZone; + selectedUnit = unit; + if (entryZone != null) + entryZone.enable(Hex.AREA, false); + entryZone = unit.entryZone; entryZone.enable(Hex.AREA, true); } - private void undo() - { - map.hexUnselect(selectedHex); - map.hexDirectionsHide(selectedHex); - map.revertEnter(activeUnit); - activeUnit = null; - selectedUnit = null; - ctrl.hud.update(); - } - private void showUnit(Unit unit, Hex hex) { - selectedUnit = unit; + activeUnit = unit; selectedHex = hex; ctrl.battle.getPlayer().reinforcement.remove(unit); - map.showOnBoard(unit, hex, entryZone.orientation); + map.setOnBoard(unit, hex, entryZone.orientation); deployedUnits.add(unit); entryZone.enable(Hex.AREA, false); showRotation(unit, hex); @@ -102,7 +87,6 @@ public class StateDeployment extends StateCommon private void showRotation(Unit unit, Hex hex) { activeUnit = unit; - selectedUnit = unit; selectedHex = hex; map.hexSelect(selectedHex); map.hexDirectionsShow(selectedHex); @@ -113,16 +97,29 @@ public class StateDeployment extends StateCommon private void deployUnit(Orientation o) { if (o == Orientation.KEEP) - o = selectedUnit.getOrientation(); - map.setOnBoard(selectedUnit, selectedHex, o); + o = activeUnit.getOrientation(); + ctrl.postOrder(map.getSetOrder(activeUnit, selectedHex, o), StateType.DEPLOYMENT); + clear(); + } - entryZone = null; + private void undeployUnit() + { + ctrl.postOrder(map.getRevertSetOrder(activeUnit), StateType.DEPLOYMENT); + ctrl.hud.update(); + clear(); + ctrl.hud.playerInfo.unitDock.show(); + } + + private void clear() + { + if (selectedHex != null) { + map.hexUnselect(selectedHex); + map.hexDirectionsHide(selectedHex); + } activeUnit = null; + entryZone = null; + selectedHex = null; selectedUnit = null; - map.hexUnselect(selectedHex); - map.hexDirectionsHide(selectedHex); ctrl.hud.actionButtons.hide(); - ctrl.hud.playerInfo.unitDock.show(); - ctrl.post(StateType.DONE); } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateEngage.java b/core/src/ch/asynk/rustanddust/game/states/StateEngage.java index bfeced8..ccd79c7 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateEngage.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateEngage.java @@ -1,89 +1,158 @@ package ch.asynk.rustanddust.game.states; +import ch.asynk.rustanddust.engine.Orientation; +import ch.asynk.rustanddust.ui.Position; import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Unit; +import ch.asynk.rustanddust.game.Order; +import ch.asynk.rustanddust.game.Ctrl.MsgType; +import ch.asynk.rustanddust.game.hud.ActionButtons.Buttons; public class StateEngage extends StateCommon { + // selectedUnit -> fire leader + // activeUnit -> target / break + + private boolean breakMove = false; + @Override public void enterFrom(StateType prevState) { if (prevState == StateType.SELECT) { - // activeUnit will be target - activeUnit = null; - if (to != null) { - // quick fire -> replay touchUp - touch(to); + breakMove = false; + if ((to != null) && (activeUnit != null)) { + // quick fire + selectTarget(activeUnit, to); } selectedUnit.showAttack(); map.hexSelect(selectedHex); + } else { + breakMove = true; + activeUnit = null; + ctrl.hud.actionButtons.show(Buttons.DONE.b); + ctrl.hud.notify("Break Through possible", Position.MIDDLE_CENTER); + map.unitsActivableShow(); + map.hexUnselect(selectedHex); } } @Override - public void leaveFor(StateType nextState) + public boolean processMsg(MsgType msg, Object data) + { + switch(msg) + { + case OK: + if (breakMove) + abortBreakMove(); + return true; + } + + return false; + } + + @Override + public void touch(Hex hex) + { + Unit unit = hex.getUnit(); + + if (!breakMove) { + if (unit == selectedUnit) + abort(); + else if ((activeUnit == null) && map.unitsTargetContains(unit)) + selectTarget(unit, hex); + else if (unit == activeUnit) + engage(); + else if ((activeUnit != null) && map.unitsActivableContains(unit)) + map.toggleAssist(unit); + } else { + if (activeUnit == null) { + if (map.unitsActivableContains(unit)) + selectBreakUnit(unit); + } else { + Orientation o = Orientation.fromAdj(to, hex); + if (o == Orientation.KEEP) + unselectBreakUnit(); + else + doRotation(o); + } + + } + } + + private void selectTarget(Unit unit, Hex hex) + { + to = hex; + activeUnit = unit; + map.unitsTargetHide(); + activeUnit.showTarget(); + map.collectAssists(selectedUnit, activeUnit, ctrl.battle.getPlayer().units); + map.unitsAssistShow(); + } + + private void engage() { + activeUnit.hideTarget(); selectedUnit.hideAttack(); map.unitsAssistHide(); - map.unitsTargetHide(); map.hexUnselect(selectedHex); - if (to != null) - map.hexUnselect(to); + Order order = map.getEngageOrder(selectedUnit, activeUnit); + + if (order.cost == 0) + ctrl.postOrder(order, StateType.ENGAGE); + else { + order.cost = order.engagement.cost; + ctrl.postOrder(order); + } } - @Override - public StateType abort() + private void abort() { + map.unitsAssistHide(); + map.unitsTargetHide(); + activeUnit.hideTarget(); + selectedUnit.hideAttack(); + map.hexUnselect(selectedHex); map.unitsActivatedClear(); - return StateType.ABORT; + ctrl.postActionAborted(); } - @Override - public StateType execute() + private void selectBreakUnit(Unit unit) { - map.unitsAssistHide(); - StateType nextState = StateType.DONE; - if (map.engageUnit(selectedUnit, activeUnit)) { - ctrl.battle.getPlayer().engagementWon += 1; - ctrl.battle.getOpponent().casualty(activeUnit); - if (map.unitsActivableSize() > 0) { - nextState = StateType.BREAK; - } - } else { - ctrl.battle.getPlayer().engagementLost += 1; - } + activeUnit = unit; + map.hexMoveShow(to); + map.hexMoveShow(unit.getHex()); + map.hexDirectionsShow(to); + map.unitsActivableHide(); + } - activeUnit.showTarget(); - ctrl.setAfterAnimationState(nextState); - return StateType.ANIMATION; + private void unselectBreakUnit() + { + map.hexMoveHide(to); + map.hexMoveHide(activeUnit.getHex()); + map.hexDirectionsHide(to); + map.unitsActivableShow(); + activeUnit = null; } - @Override - public void touch(Hex hex) + private void doRotation(Orientation o) { - Unit unit = hex.getUnit(); + map.hexMoveHide(to); + map.hexMoveHide(activeUnit.getHex()); + map.hexDirectionsHide(to); + map.pathsInit(activeUnit); + map.pathsBuild(to); + map.pathsChooseShortest(); + map.pathsSetOrientation(o); + ctrl.postOrder(map.getMoveOrder(activeUnit, false)); + } - // activeUnit is the target, selectedTarget is the engagement leader - if (unit == selectedUnit) { - ctrl.post(StateType.ABORT); - } else if ((activeUnit == null) && map.unitsTargetContains(unit)) { - // ctrl.hud.notify("Engage " + unit); - map.unitsTargetHide(); - to = hex; - activeUnit = unit; - activeUnit.showTarget(); - map.collectAssists(selectedUnit, activeUnit, ctrl.battle.getPlayer().units); - map.unitsAssistShow(); - } - else if (unit == activeUnit) { - ctrl.post(StateType.DONE); - } - else if ((activeUnit != null) && map.unitsActivableContains(unit)) { - map.toggleAssist(unit); - // if (map.toggleAssist(unit)) - // ctrl.hud.notify(unit + " will fire"); - // else - // ctrl.hud.notify(unit + " wont fire"); - } + private void abortBreakMove() + { + if (activeUnit != null) + map.hexMoveHide(activeUnit.getHex()); + map.hexMoveHide(to); + map.hexDirectionsHide(to); + map.unitsActivableHide(); + ctrl.postOrder(Order.END); } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateMove.java b/core/src/ch/asynk/rustanddust/game/states/StateMove.java index 3aa684d..ae0c751 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateMove.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateMove.java @@ -1,103 +1,125 @@ package ch.asynk.rustanddust.game.states; -import ch.asynk.rustanddust.ui.Position; +import ch.asynk.rustanddust.engine.Orientation; import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Unit; +import ch.asynk.rustanddust.game.Order; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.game.hud.ActionButtons.Buttons; public class StateMove extends StateCommon { + enum State + { + SHOW, + PATH, + ROTATE, + EXIT + } + + private State state; + private boolean enter; + private boolean hqMode; + private boolean notFirst; + @Override public void enterFrom(StateType prevState) { - ctrl.hud.actionButtons.show( - ((map.unitsActivatedSize() > 0) ? Buttons.DONE.b : 0) - ); + state = State.SHOW; - if (prevState == StateType.WITHDRAW) { - completePath(map.pathsSize()); - return; - } + enter = false; + hqMode = false; + notFirst = false; map.pathsClear(); - if (prevState == StateType.SELECT) { - // use selectedHex and selectedUnit + map.hexSelect(selectedHex); + map.pathsInit(selectedUnit); activeUnit = selectedUnit; - map.pathsInit(activeUnit); - map.collectUpdate(activeUnit); - if (to != null) { - // quick move -> replay touchUp - touch(to); - } else - checkExit(activeUnit); - } else { - // back from rotation -> chose next Pawn - if (selectedUnit.canMove()) { - changeUnit(selectedUnit); + if (to == null) { + hqMode = true; + map.movesShow(); + } else { + collectPaths(to); + } + } else if (prevState == StateType.REINFORCEMENT) { + enter = true; + map.hexSelect(selectedHex); + map.pathsInit(selectedUnit); + if (selectedUnit.getMovementPoints() > 0) { + map.movesCollect(selectedUnit); + map.movesShow(); } else { - changeUnit(map.unitsMoveableGet(0)); + to = selectedHex; + showRotation(to); + collectPaths(to); } + } else { + notFirst = hqMode = true; + selectNextUnit(); } - map.unitsActivableShow(); + if (hqMode) + map.unitsActivableShow(); activeUnit.hideActiveable(); + int n = (notFirst ? Buttons.DONE.b : 0); + n |= (enter ? Buttons.ABORT.b : 0); + ctrl.hud.actionButtons.show(n); } @Override - public void leaveFor(StateType nextState) + public boolean processMsg(MsgType msg, Object data) { - if (nextState == StateType.WITHDRAW) - return; - - // hide all but assists : want them when in rotation - activeUnit.hideActiveable(); - map.movesHide(); - map.hexUnselect(activeUnit.getHex()); - if (to != null) - map.pathHide(to); - - if (nextState != StateType.SELECT) { - if (to == null) - to = activeUnit.getHex(); - } - } - - @Override - public StateType abort() - { - hideActivable(); - if (activeUnit.justEntered()) { - map.revertEnter(activeUnit); - return StateType.ABORT; + switch(msg) + { + case OK: + if (state == State.EXIT) { + exit(); + return true; + } + if (hqMode) { + endHqMode(); + return true; + } + break; + case CANCEL: + if (enter || (state == State.PATH) || (state == State.ROTATE)) { + abortMove(); + return true; + } + if (state == State.EXIT) { + abortExit(); + return true; + } + break; } - int n = map.unitsActivatedSize(); - if (n == 0) - return StateType.ABORT; - map.revertMoves(); - return StateType.ANIMATION; - } - @Override - public StateType execute() - { - hideActivable(); - // be sure that the hq is activated - if (selectedUnit.canMove() && (map.unitsActivatedSize() > 0)) - selectedUnit.setMoved(); - - return StateType.DONE; + return false; } @Override public void touch(Hex hex) { + if (state == State.ROTATE) { + if (hex == to) + abortMove(); + else { + Orientation o = Orientation.fromAdj(to, hex); + if (o != Orientation.KEEP) + move(o); + else if (hex == activeUnit.getHex()) + abortMove(); + } + return; + } + if (hex == activeUnit.getHex()) { if (to != null) map.pathHide(to); - to = null; + map.pathsHide(); map.pathsClear(); - ctrl.post(StateType.ROTATE); + map.pathsInit(activeUnit); + collectPaths(hex); return; } @@ -107,21 +129,29 @@ public class StateMove extends StateCommon if (map.unitsActivableContains(unit)) { if (unit != activeUnit) - changeUnit(unit); + selectUnit(unit); } else if ((s == 0) && map.movesContains(hex)) { collectPaths(hex); + } else if ((s > 1) && hex == to) { + s = map.pathsChooseBest(); + if (s == 1) + showRotation(to); } else if (map.pathsContains(hex)) { togglePoint(hex, s); } } - private void hideActivable() + private void selectNextUnit() { - map.unitsActivableHide(); + if (selectedUnit.canMove()) + selectUnit(selectedUnit); + else + selectUnit(map.getFirstActivable()); } - private void changeUnit(Unit unit) + private void selectUnit(Unit unit) { + state = State.SHOW; if (activeUnit != null ) { map.hexUnselect(activeUnit.getHex()); if (activeUnit.canMove()) @@ -130,70 +160,170 @@ public class StateMove extends StateCommon to = null; activeUnit = unit; activeUnit.hideActiveable(); - Hex hex = activeUnit.getHex(); - map.pathsInit(activeUnit, hex); + map.hexSelect(activeUnit.getHex()); + map.pathsClear(); + map.pathsInit(activeUnit); map.movesHide(); map.movesCollect(activeUnit); map.movesShow(); - map.hexSelect(hex); - ctrl.hud.notify(activeUnit.toString(), Position.TOP_CENTER); - checkExit(activeUnit); + ctrl.hud.notify(activeUnit.toString()); } private void collectPaths(Hex hex) { + state = State.PATH; to = hex; map.movesHide(); map.hexMoveShow(to); - int s = map.pathsBuild(to); - if (!checkExit(activeUnit, hex)) - completePath(s); + if (!checkExit(to)) + completePath(); + ctrl.hud.actionButtons.show(Buttons.ABORT.b); } - private void completePath(int s) + private void completePath() { + int s = map.pathsBuild(to); if (cfg.autoPath && (s > 1)) s = map.pathsChooseBest(); map.pathsShow(); if (s == 1) - ctrl.post(StateType.ROTATE); + showRotation(to); } private void togglePoint(Hex hex, int s) { - if (hex == activeUnit.getHex()) { - // - } else if (hex == to) { - // - } else { - map.pathsHide(); - s = map.pathsToggleHex(hex); - map.pathsShow(); - } - - if (s == 1) { - if (!checkExit(activeUnit, hex)) - ctrl.post(StateType.ROTATE); - } + map.pathsHide(); + s = map.pathsToggleHex(hex); + map.pathsShow(); + if (s == 1) + showRotation(to); } - private boolean checkExit(Unit unit) + private boolean checkExit(Hex hex) { - if (unit.justEntered()) + if (enter) return false; - if ((unit.exitZone == null) || !unit.exitZone.contains(unit.getHex())) + if ((activeUnit.exitZone == null) || !activeUnit.exitZone.contains(hex)) return false; - ctrl.post(StateType.WITHDRAW); + + int s = map.pathsBuild(to); + + if (!map.pathsCanExit(activeUnit.exitZone.orientation)) + return false; + + if (map.pathsChooseExit(activeUnit.exitZone.orientation) > 1) + throw new RuntimeException(String.format("pathsChooseExit() -> %d", map.pathsSize())); + map.pathShow(hex); + + state = State.EXIT; + ctrl.hud.askExitBoard(); return true; } - private boolean checkExit(Unit unit, Hex hex) + private void showRotation(Hex hex) { - if ((unit.exitZone == null) || !unit.exitZone.contains(hex)) - return false; - if (!map.pathsCanExit(unit.exitZone.orientation)) - return false; - ctrl.post(StateType.WITHDRAW); - return true; + state = State.ROTATE; + map.movesHide(); + map.pathsHide(); + map.pathShow(hex); + map.hexDirectionsShow(hex); + ctrl.hud.actionButtons.show(Buttons.ABORT.b); + } + + private void move(Orientation o) + { + map.pathsSetOrientation(o); + if (enter) + completeMove(map.getEnterOrder(selectedUnit, hqMode)); + else + completeMove(map.getMoveOrder(selectedUnit, hqMode)); + } + + private void exit() + { + if (map.pathsTo() == null) { + map.pathsBuild(to); + if (map.pathsChooseExit(activeUnit.exitZone.orientation) > 1) + throw new RuntimeException(String.format("pathsChooseExit() -> %d", map.pathsSize())); + } + + completeMove(map.getExitOrder(selectedUnit, hqMode)); + } + + private void completeMove(Order order) + { + map.pathHide(to); + map.hexDirectionsHide(to); + map.hexUnselect(selectedHex); + if (order.cost == 0) + ctrl.postOrder(order, StateType.MOVE); + else + ctrl.postOrder(order); + } + + private void endHqMode() + { + if (selectedUnit.canMove()) + selectedUnit.setMoved(); + clear(); + ctrl.postOrder(Order.END); + } + + private void abortMove() + { + if (enter) { + map.revertEnter(activeUnit); + ctrl.battle.getPlayer().revertUnitEntry(activeUnit); + ctrl.hud.update(); + } + clear(); + if (notFirst) { + // FIXME abortMove : cfg.revertAllMoves + // if (cfg.revertAllMoves) { + // map.revertMoves(); + // ctrl.postTransitionToAborted(); + // } else { + selectUnit(activeUnit); + abortCompleted(); + // } + } + else + ctrl.postActionAborted(); + } + + private void abortExit() + { + map.pathHide(to); + if (to == null) { + state = State.SHOW; + } else { + state = State.PATH; + map.hexMoveShow(to); + completePath(); + } + abortCompleted(); + } + + private void abortCompleted() + { + if (hqMode) + map.unitsActivableShow(); + activeUnit.hideActiveable(); + ctrl.hud.actionButtons.show((notFirst ? Buttons.DONE.b : 0)); + } + + private void clear() + { + state = State.SHOW; + map.movesHide(); + map.pathsHide(); + activeUnit.hideActiveable(); + map.hexUnselect(activeUnit.getHex()); + map.unitsActivableHide(); + if (to != null) { + map.pathHide(to); + map.hexDirectionsHide(to); + } + map.pathsClear(); } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StatePromote.java b/core/src/ch/asynk/rustanddust/game/states/StatePromote.java index bfec208..774b1a9 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StatePromote.java +++ b/core/src/ch/asynk/rustanddust/game/states/StatePromote.java @@ -5,26 +5,6 @@ public class StatePromote extends StateCommon @Override public void enterFrom(StateType prevState) { - ctrl.setAfterAnimationState(StateType.DONE); - ctrl.post(StateType.ANIMATION); - map.promoteUnit(selectedUnit); - } - - @Override - public void leaveFor(StateType nextState) - { - map.hexUnselect(selectedHex); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } - - @Override - public StateType execute() - { - return StateType.DONE; + ctrl.postOrder(map.getPromoteOrder(selectedUnit)); } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateReinforcement.java b/core/src/ch/asynk/rustanddust/game/states/StateReinforcement.java index e118924..ffb1f24 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateReinforcement.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateReinforcement.java @@ -3,6 +3,7 @@ package ch.asynk.rustanddust.game.states; import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Zone; import ch.asynk.rustanddust.game.Unit; +import ch.asynk.rustanddust.game.Ctrl.MsgType; public class StateReinforcement extends StateCommon { @@ -11,70 +12,53 @@ public class StateReinforcement extends StateCommon @Override public void enterFrom(StateType prevState) { - map.clearAll(); - if (selectedHex != null) - map.hexUnselect(selectedHex); + map.clear(); entryZone = null; + activeUnit = null; selectedHex = null; + selectedUnit = null; ctrl.hud.playerInfo.unitDock.show(); } @Override - public void leaveFor(StateType nextState) + public boolean processMsg(MsgType msg, Object data) { - if (selectedHex != null) - map.hexUnselect(selectedHex); - if (entryZone != null) - entryZone.enable(Hex.AREA, false); - ctrl.hud.playerInfo.unitDock.hide(); - } - - @Override - public StateType abort() - { - return StateType.ABORT; - } + switch(msg) + { + case UNIT_DOCK_SELECT: + showEntryZone((Unit) data); + return true; + } - @Override - public StateType execute() - { - return StateType.DONE; + return false; } @Override public void touch(Hex hex) { - Unit unit = ctrl.hud.playerInfo.unitDock.selectedUnit; - if (hex == null) - changeUnit(unit); - else if ((entryZone != null) && hex.isEmpty() && entryZone.contains(hex)) - unitEnter(activeUnit, hex); - else - ctrl.post(StateType.SELECT); + if ((entryZone != null) && hex.isEmpty() && entryZone.contains(hex)) + unitEnter(selectedUnit, hex); } - private void changeUnit(Unit unit) + private void showEntryZone(Unit unit) { - activeUnit = unit; + selectedUnit = unit; if (entryZone != null) entryZone.enable(Hex.AREA, false); - entryZone = activeUnit.entryZone; + entryZone = unit.entryZone; entryZone.enable(Hex.AREA, true); } private void unitEnter(Unit unit, Hex hex) { - selectedUnit = unit; + activeUnit = unit; selectedHex = hex; - map.hexSelect(selectedHex); + map.enterBoard(unit, hex, entryZone); entryZone.enable(Hex.AREA, false); - if (map.enterBoard(unit, hex, entryZone.allowedMoves)) { - if (unit.getMovementPoints() > 0) - ctrl.post(StateType.MOVE); - else - ctrl.post(StateType.ROTATE); - } else { - ctrl.hud.notify("Can not enter the map at that position"); - } + ctrl.battle.getPlayer().reinforcement.remove(unit); + ctrl.hud.playerInfo.unitDock.hide(); + ctrl.hud.update(); + ctrl.post(StateType.MOVE); + entryZone = null; } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateReplay.java b/core/src/ch/asynk/rustanddust/game/states/StateReplay.java index ec8295d..22105fb 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateReplay.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateReplay.java @@ -1,87 +1,111 @@ package ch.asynk.rustanddust.game.states; import ch.asynk.rustanddust.game.Order; +import ch.asynk.rustanddust.game.Ctrl.MsgType; public class StateReplay extends StateCommon { - private Order order; + private Order order = null; @Override public void enterFrom(StateType prevState) { + if (this.order != null) + replayStep(); + Order o = map.stepReplay(); if (o == null) { - StateType nextState = nextState(); + ctrl.postReplayDone(replayDone()); order = null; - ctrl.post(nextState); } else { this.order = o; setup(); - map.replay(order); - ctrl.setAfterAnimationState(StateType.REPLAY); - ctrl.post(StateType.ANIMATION); + ctrl.postOrder(o, StateType.REPLAY); } } private void setup() { - int s = order.activable.size(); + int s = order.activables.size(); - switch (order.type) { + switch (order.type) + { case MOVE: - selectedUnit = ((s > 0) ? order.activable.get(s - 1) : order.unit); + selectedUnit = order.leader; break; case ENGAGE: to = order.engagement.defender.getHex(); - if (order.engagement.success) { - ctrl.battle.getPlayer().engagementWon += 1; - ctrl.battle.getOpponent().casualty(order.engagement.defender); - } else { - ctrl.battle.getPlayer().engagementLost += 1; - } break; + case PROMOTE: default: break; } } - private StateType nextState() + private void replayStep() { - if (map.unitsActivableSize() <= 0) - return StateType.DONE; - - StateType next = null; - - switch (order.type) { + switch (order.type) + { case MOVE: - next = StateType.MOVE; + moveReplayStep(); break; case ENGAGE: - next = StateType.BREAK; - break; + case PROMOTE: default: - next = StateType.DONE; break; } - - return next; } - @Override - public void leaveFor(StateType nextState) + private void moveReplayStep() { + switch(order.move.type) + { + case SET: + ctrl.sendMsg(MsgType.UNIT_DEPLOYED, order.move.pawn); + break; + case REGULAR: + case EXIT: + case ENTER: + break; + } } - @Override - public StateType abort() + private StateType replayDone() { - return StateType.ABORT; + if (order == null) return null; + + boolean more = (order.activables.size() > 0); + StateType nextState = null; + switch (order.type) + { + case MOVE: + nextState = moveReplayDone(more); + break; + case ENGAGE: + if (more) nextState = StateType.ENGAGE; + break; + case PROMOTE: + default: + break; + } + return nextState; } - @Override - public StateType execute() + private StateType moveReplayDone(boolean more) { - // called at the end of animation DONE -> burn 1 AP - return ((order.cost == 0) ? StateType.REPLAY : StateType.DONE); + StateType nextState = null; + switch(order.move.type) + { + case REGULAR: + case EXIT: + if (more) nextState = StateType.MOVE; + break; + case SET: + nextState = StateType.DEPLOYMENT; + break; + case ENTER: + break; + } + return nextState; } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateRotate.java b/core/src/ch/asynk/rustanddust/game/states/StateRotate.java deleted file mode 100644 index 4aa9608..0000000 --- a/core/src/ch/asynk/rustanddust/game/states/StateRotate.java +++ /dev/null @@ -1,103 +0,0 @@ -package ch.asynk.rustanddust.game.states; - -import ch.asynk.rustanddust.engine.Orientation; -import ch.asynk.rustanddust.game.Hex; -import ch.asynk.rustanddust.RustAndDust; - -public class StateRotate extends StateCommon -{ - private boolean rotateOnly; - private boolean rotationSet; - - @Override - public void enterFrom(StateType prevState) - { - if (!cfg.showMoveAssists) map.unitsActivableHide(); - - if (activeUnit == null) - activeUnit = selectedUnit; - if (to == null) - to = activeUnit.getHex(); - - if (!map.pathsIsSet()) { - map.pathsInit(activeUnit); - map.pathsBuild(to); - } - - if (map.pathsSize() > 1) - RustAndDust.debug("ERROR: Rotate pathsSize() == " + map.pathsSize()); - - rotateOnly = (to == activeUnit.getHex()); - - if (!rotateOnly) - map.pathShow(to); - map.hexSelect(activeUnit.getHex()); - map.hexDirectionsShow(to); - - rotationSet = false; - } - - @Override - public void leaveFor(StateType nextState) - { - map.hexUnselect(activeUnit.getHex()); - map.pathHide(to); - map.hexDirectionsHide(to); - map.pathsClear(); - to = null; - } - - @Override - public StateType abort() - { - StateType nextState = StateType.ABORT; - ctrl.hud.actionButtons.hide(); - if (activeUnit.justEntered()) { - map.revertEnter(activeUnit); - nextState = StateType.ABORT; - } else if (map.unitsActivatedSize() == 0) { - map.unitsActivableHide(); - } else { - nextState = StateType.MOVE; - } - return nextState; - } - - @Override - public StateType execute() - { - if (!rotationSet) - return StateType.DONE; - - StateType whenDone = StateType.DONE; - - if (map.moveUnit(activeUnit)) { - if (map.unitsActivableSize() > 0) - whenDone = StateType.MOVE; - } else - RustAndDust.debug("rotate failed"); - - ctrl.setAfterAnimationState(whenDone); - return StateType.ANIMATION; - } - - @Override - public void touch(Hex hex) - { - if (rotationSet) return; - - Orientation o = Orientation.fromAdj(to, hex); - if (o == Orientation.KEEP) { - ctrl.post(StateType.ABORT); - return; - } - - if (!activeUnit.justEntered() && rotateOnly && (o == activeUnit.getOrientation())) - return; - - map.pathsSetOrientation(o); - rotationSet = true; - execute(); - ctrl.post(StateType.ANIMATION); - } -} diff --git a/core/src/ch/asynk/rustanddust/game/states/StateSelect.java b/core/src/ch/asynk/rustanddust/game/states/StateSelect.java index 518258f..f6c42c3 100644 --- a/core/src/ch/asynk/rustanddust/game/states/StateSelect.java +++ b/core/src/ch/asynk/rustanddust/game/states/StateSelect.java @@ -1,120 +1,131 @@ package ch.asynk.rustanddust.game.states; +import ch.asynk.rustanddust.RustAndDust; import ch.asynk.rustanddust.ui.Position; import ch.asynk.rustanddust.game.Hex; import ch.asynk.rustanddust.game.Unit; +import ch.asynk.rustanddust.game.Ctrl.MsgType; import ch.asynk.rustanddust.game.hud.ActionButtons.Buttons; -import ch.asynk.rustanddust.RustAndDust; public class StateSelect extends StateCommon { - @Override - public void enterFrom(StateType prevState) - { - to = null; - selectedHex = null; - selectedUnit = null; - activeUnit = null; - map.clearAll(); - ctrl.hud.actionButtons.hide(); - } + private boolean isEnemy; @Override - public void leaveFor(StateType nextState) + public void enterFrom(StateType prevState) { - hidePossibilities(); + clear(); } @Override - public StateType abort() + public boolean processMsg(MsgType msg, Object data) { - if (selectedHex != null) - map.hexUnselect(selectedHex); - hidePossibilities(); - map.clearAll(); - return StateType.ABORT; - } + switch(msg) + { + case OK: + ctrl.postTurnDone(); + return true; + case PROMOTE: + changeTo(StateType.PROMOTE); + return true; + } - @Override - public StateType execute() - { - return StateType.DONE; + return false; } @Override public void touch(Hex hex) { - if (!isEnemy) { + Unit unit = hex.getUnit(); + + if (!isEnemy && (selectedUnit != null)) { if (map.movesContains(hex)) { // quick move to = hex; - ctrl.post(StateType.MOVE); + changeTo(StateType.MOVE); return; } - if (map.unitsTargetContains(hex.getUnit())) { + if (map.unitsTargetContains(unit)) { // quick fire to = hex; - ctrl.post(StateType.ENGAGE); + activeUnit = unit; + changeTo(StateType.ENGAGE); return; } } - if (selectedHex != null) - map.hexUnselect(selectedHex); + hide(); - hidePossibilities(); - if (hex.isOffMap()) { - selectedUnit = null; - return; - } - - Unit unit = hex.getUnit(); - - if (unit == null) { - isEnemy = false; - ctrl.hud.actionButtons.hide(); - map.clearAll(); + if ((unit == null) || hex.isOffMap()) { selectedUnit = null; return; } isEnemy = ctrl.battle.getPlayer().isEnemy(unit); - if (!isEnemy && (unit == selectedUnit) && unit.canMove()) { + + if (!isEnemy && (selectedUnit == unit) && unit.canMove()) { if (unit.isHq() && (map.unitsActivableSize() > 1)) { - ctrl.hud.notify("HQ activation"); - select(hex, unit, isEnemy); - ctrl.post(StateType.MOVE); - } else { - // quick rotate + ctrl.hud.notify("HQ activation", Position.MIDDLE_CENTER); + to = null; + } else to = hex; - ctrl.post(StateType.ROTATE); - } + changeTo(StateType.MOVE); } else { - select(hex, unit, isEnemy); - ctrl.hud.notify(selectedUnit.toString(), Position.TOP_CENTER); + select(hex, unit); + ctrl.hud.notify(selectedUnit.toString()); } } - private void select(Hex hex, Unit unit, boolean isEnemy) + private void select(Hex hex, Unit unit) { selectedHex = hex; selectedUnit = unit; + RustAndDust.debug(String.format(" %s - %s", selectedUnit, selectedHex)); + + map.hexSelect(selectedHex); if (isEnemy && !cfg.showEnemyPossibilities) return; - int moves = map.movesCollect(selectedUnit); - int targets = map.collectTargets(selectedUnit, (isEnemy ? ctrl.battle.getPlayer() : ctrl.battle.getOpponent()).units); - - if (moves > 0) + if(map.movesCollect(selectedUnit) > 0) { map.collectMoveable(selectedUnit); + if (cfg.showMoves) map.movesShow(); + if (cfg.showMoveAssists) map.unitsActivableShow(); + unit.hideActiveable(); + } - if ((moves > 0) || (targets > 0)) { - map.hexSelect(selectedHex); - showPossibilities(selectedUnit); + if (map.collectTargets(selectedUnit, (isEnemy ? ctrl.battle.getPlayer() : ctrl.battle.getOpponent()).units) > 0) { + if (cfg.showTargets) map.unitsTargetShow(); + unit.hideActiveable(); } ctrl.hud.actionButtons.show((ctrl.battle.getPlayer().canPromote(selectedUnit)) ? Buttons.PROMOTE.b : 0 ); - RustAndDust.debug("Select", selectedHex.toString() + " " + selectedUnit + (isEnemy ? " enemy " : " friend ")); + } + + private void changeTo(StateType nextState) + { + hide(); + ctrl.post(nextState); + } + + private void hide() + { + if (selectedHex != null) + map.hexUnselect(selectedHex); + map.movesHide(); + map.unitsTargetHide(); + map.unitsActivableHide(); + ctrl.hud.actionButtons.hide(); + } + + private void clear() + { + hide(); + map.clear(); + to = null; + isEnemy = false; + selectedHex = null; + selectedUnit = null; + activeUnit = null; } } diff --git a/core/src/ch/asynk/rustanddust/game/states/StateWithdraw.java b/core/src/ch/asynk/rustanddust/game/states/StateWithdraw.java deleted file mode 100644 index f21fbed..0000000 --- a/core/src/ch/asynk/rustanddust/game/states/StateWithdraw.java +++ /dev/null @@ -1,64 +0,0 @@ -package ch.asynk.rustanddust.game.states; - -import ch.asynk.rustanddust.game.Hex; -import ch.asynk.rustanddust.game.Unit; -import ch.asynk.rustanddust.RustAndDust; - -public class StateWithdraw extends StateCommon -{ - @Override - public void enterFrom(StateType prevState) - { - ctrl.hud.askExitBoard(); - } - - @Override - public void leaveFor(StateType nextState) - { - } - - @Override - public StateType abort() - { - return StateType.MOVE; - } - - @Override - public StateType execute() - { - if (activeUnit == null) - activeUnit = selectedUnit; - - ctrl.setAfterAnimationState(withdraw(activeUnit)); - return StateType.ANIMATION; - } - - private StateType withdraw(Unit unit) - { - Hex hex = unit.getHex(); - - // rotation - if (map.pathsTo() == null) - map.pathsBuild(hex); - - Hex exitHex = (Hex) map.pathsTo(); - if (!unit.exitZone.contains(exitHex)) - throw new RuntimeException(String.format("%s not in exitZone", exitHex)); - - if (map.pathsChooseExit(unit.exitZone.orientation) > 1) - RustAndDust.debug("ERROR: Withdraw pathsSize() == " + map.pathsSize()); - - unit.hideActiveable(); - if (to != null) - map.pathHide(to); - map.movesHide(); - map.hexUnselect(hex); - - if (map.exitBoard(unit)) { - if (map.unitsActivableSize() > 0) - return StateType.MOVE; - } else - RustAndDust.debug("exit failed"); - return StateType.DONE; - } -} diff --git a/core/src/ch/asynk/rustanddust/menu/PlayMenu.java b/core/src/ch/asynk/rustanddust/menu/PlayMenu.java index 78fbe85..3fd0d4e 100644 --- a/core/src/ch/asynk/rustanddust/menu/PlayMenu.java +++ b/core/src/ch/asynk/rustanddust/menu/PlayMenu.java @@ -142,11 +142,11 @@ public class PlayMenu extends Patch implements MenuCtrl.Panel return MenuCtrl.MenuType.OKKO; } else if (resumeBtn.hit(x, y)) { game.playType(); - return setConfig(Config.LoadMode.LOAD); + return setConfig(Config.LoadMode.RESUME); } else if (replayBtn.hit(x, y)) { game.playType(); - // TODO chose between : REPLAY_LAST / REPLAY_ALL - return setConfig(Config.LoadMode.REPLAY_LAST); + // TODO chose between : REPLAY_CURRENT / REPLAY_ALL + return setConfig(Config.LoadMode.REPLAY_CURRENT); } else if (list.hit(x, y)) { if (i != getList().getIdx()) game.playType(); diff --git a/core/src/ch/asynk/rustanddust/screens/GameScreen.java b/core/src/ch/asynk/rustanddust/screens/GameScreen.java index e2aa8a2..b3d2457 100644 --- a/core/src/ch/asynk/rustanddust/screens/GameScreen.java +++ b/core/src/ch/asynk/rustanddust/screens/GameScreen.java @@ -149,7 +149,7 @@ public class GameScreen implements Screen blocked = false; } - ctrl.processEvent(); + ctrl.processEvent(delta); ctrl.hud.animate(delta); ctrl.map.animate(delta); diff --git a/core/src/ch/asynk/rustanddust/util/DB.java b/core/src/ch/asynk/rustanddust/util/DB.java index 994e5d3..c5c68c3 100644 --- a/core/src/ch/asynk/rustanddust/util/DB.java +++ b/core/src/ch/asynk/rustanddust/util/DB.java @@ -42,7 +42,8 @@ public class DB + " ,mode integer not null, battle integer not null, opponent integer not null" + " ,turn integer not null, currentPlayer integer default null" + " ,ts datetime default current_timestamp, synched integer default 0" - + " ,state text default null, stateH text default null" + + " ,players text default null, playersH text default null" + + " ,map text default null, mapH text default null" + " ,orders text default null, ordersH text default null" + " ,foreign key (battle) references battles(_id)" + " ,foreign key (opponent) references players(_id)" @@ -53,7 +54,8 @@ public class DB private static final String TBL_TURNS_CRT = "create table if not exists" + " turns ( _id integer primary key autoincrement" + " ,game integer not null, turn integer not null, currentPlayer integer not null" - + " ,state text default null, stateH text default null" + + " ,players text default null, playersH text default null" + + " ,map text default null, mapH text default null" + " ,orders text default null, ordersH text default null" + " ,foreign key (game) references games(_id)" + " ,foreign key (currentPlayer) references players(_id)" @@ -126,6 +128,7 @@ public class DB private boolean checkDigest(String what, int id, String payload, String digest) { + if (payload == null) return true; if (digest.equals(getDigest(payload))) return true; RustAndDust.error(String.format("corrupted %s(%d)", what, id)); @@ -258,15 +261,18 @@ public class DB return getGameId(opponent, battle, mode); } - private static final String STORE_GAME_STATE = "update games set ts=current_timestamp, turn=%d, currentPlayer=%d, state='%s', stateH='%s', synched=1 where _id=%d;"; + private static final String STORE_GAME_STATE = "update games set ts=current_timestamp, turn=%d, currentPlayer=%d," + + " players='%s', playersH='%s', map='%s', mapH='%s', synched=1 where _id=%d;"; - public boolean storeGameState(int game, int turn, int player, String state) + public boolean storeGameState(int game, int turn, int player, String players, String map) { RustAndDust.debug("storeGameState"); try { - String hash = getDigest(state); - if (hash == null) return false; - exec(String.format(STORE_GAME_STATE, turn, player, state, hash, game)); + String playersH = getDigest(players); + if (playersH == null) return false; + String mapH = getDigest(map); + if (mapH == null) return false; + exec(String.format(STORE_GAME_STATE, turn, player, players, playersH, map, mapH, game)); } catch (SQLiteGdxException e) { RustAndDust.error("storeGameState"); return false; @@ -280,9 +286,9 @@ public class DB { RustAndDust.debug("storeGameOrders"); try { - String hash = getDigest(orders); - if (hash == null) return false; - exec(String.format(STORE_GAME_ORDERS, turn, player, orders, hash, game)); + String ordersH = getDigest(orders); + if (ordersH == null) return false; + exec(String.format(STORE_GAME_ORDERS, turn, player, orders, ordersH, game)); } catch (SQLiteGdxException e) { RustAndDust.error("storeGameOrders"); return false; @@ -290,15 +296,28 @@ public class DB return true; } - private static final String COPY_TURN = "insert into turns(game, turn, currentPlayer, state, stateH, orders, ordersH)" - + " select _id, turn, currentPlayer, state, stateH, orders, ordersH from games where _id=%d;"; + private static final String COPY_TURN = "insert into turns(game, turn, currentPlayer, players, playersH, map, mapH, orders, ordersH)" + + " select _id, turn, currentPlayer, players, playersH, map, mapH, orders, ordersH from games where _id=%d;"; - public boolean storeLastTurn(int game) + public boolean storeCurrentTurn(int game) { + RustAndDust.debug("storeCurrentTurn"); try { exec(String.format(COPY_TURN, game)); } catch (SQLiteGdxException e) { - RustAndDust.error("storeLastTurn"); + RustAndDust.error("storeCurrentTurn"); + return false; + } + return true; + } + + public boolean clearGameOrders(int game) + { + RustAndDust.debug("clearGameOrders"); + try { + exec(String.format("update games set orders=null, ordersH=null, synched=1 where _id=%d;", game)); + } catch (SQLiteGdxException e) { + RustAndDust.error("clearGameOrders"); return false; } return true; @@ -306,7 +325,7 @@ public class DB private static final String LOAD_BASE = "select g._id, g.mode, g.battle, g.opponent, g.turn, g.currentPlayer, g.ts, g.synched"; - private static final String LOAD_GAMES = LOAD_BASE + ", null, null, null, null, p.name, b.name" + private static final String LOAD_GAMES = LOAD_BASE + ", null, null, null, null, null, null, p.name, b.name" + " from games g inner join players p on (p._id=g.opponent) inner join battles b on (b._id=g.battle);"; public void loadGames() @@ -325,46 +344,40 @@ public class DB } catch (SQLiteGdxException e) { RustAndDust.error("loadGames"); } } - private static final String LOAD_GAME = LOAD_BASE + ", g.state, g.stateH, g.orders, g.ordersH, null, null from games g where g._id=%d;"; + private static final String LOAD_GAME = LOAD_BASE + ", g.players, g.playersH, g.map, g.mapH, g.orders, g.ordersH, null, null from games g where g._id=%d;"; public GameRecord loadGame(int game) { RustAndDust.debug("loadGame"); - GameRecord r = null; - try { - DatabaseCursor cursor = query(String.format(LOAD_GAME, game)); - if (cursor.getCount() > 0) { - cursor.next(); - r = gameRecordFrom(cursor); - if (!checkDigest("GameState", game, r.state, r.stateH)) - r = null; - else if(!checkDigest("GameOrders", game, r.orders, r.ordersH)) - r = null; - } - } catch (SQLiteGdxException e) { RustAndDust.error("loadGame"); } - if (r == null) - deleteGame(game); - return r; + return loadGame(game, LOAD_GAME, "loadGAME"); } - private static final String LOAD_LAST_TURN = "select g._id, g.mode, g.battle, g.opponent, t.turn, t.currentPlayer, g.ts, g.synched" - + ", t.state, t.stateH, g.orders, g.ordersH, null, null from games g inner join turns t on (g._id = t.game) where g._id=%d order by t.turn desc limit 1;"; + private static final String LOAD_LAST_TURN = "select g._id, g.mode, g.battle, g.opponent, g.turn, g.currentPlayer, g.ts, g.synched" + + ", t.players, t.playersH, t.map, t.mapH, g.orders, g.ordersH, null, null" + +" from games g inner join turns t on (g._id = t.game) where g._id=%d order by t.turn desc limit 1;"; public GameRecord loadLastTurn(int game) { RustAndDust.debug("loadLastTurn"); + return loadGame(game, LOAD_LAST_TURN, "loadLastTurn"); + } + + private GameRecord loadGame(int game, String sql, String errMsg) + { GameRecord r = null; try { - DatabaseCursor cursor = query(String.format(LOAD_LAST_TURN, game)); + DatabaseCursor cursor = query(String.format(sql, game)); if (cursor.getCount() > 0) { cursor.next(); r = gameRecordFrom(cursor); - if (!checkDigest("GameState", game, r.state, r.stateH)) + if (!checkDigest("GameState", game, r.players, r.playersH)) + r = null; + if (!checkDigest("GameState", game, r.map, r.mapH)) r = null; else if(!checkDigest("GameOrders", game, r.orders, r.ordersH)) r = null; } - } catch (SQLiteGdxException e) { RustAndDust.error("loadLastTurn"); } + } catch (SQLiteGdxException e) { RustAndDust.error(errMsg); } if (r == null) deleteGame(game); return r; @@ -404,13 +417,15 @@ public class DB RustAndDust.error(String.format("can't parse", cursor.getString(6))); } r.synched = ((cursor.getInt(7) == 1) ? true : false); - r.state = cursor.getString(8); - r.stateH = cursor.getString(9); - r.orders = cursor.getString(10); - r.ordersH = cursor.getString(11); + r.players = cursor.getString(8); + r.playersH = cursor.getString(9); + r.map = cursor.getString(10); + r.mapH = cursor.getString(11); + r.orders = cursor.getString(12); + r.ordersH = cursor.getString(13); // - r.oName = cursor.getString(12); - r.bName = cursor.getString(13); + r.oName = cursor.getString(14); + r.bName = cursor.getString(15); } catch (Exception e) { r.dispose(); RustAndDust.error("GameRecord from cursor"); } diff --git a/core/src/ch/asynk/rustanddust/util/GameRecord.java b/core/src/ch/asynk/rustanddust/util/GameRecord.java index 5693a3e..4a540ba 100644 --- a/core/src/ch/asynk/rustanddust/util/GameRecord.java +++ b/core/src/ch/asynk/rustanddust/util/GameRecord.java @@ -21,8 +21,10 @@ public class GameRecord implements List.ListElement, Disposable, Pool.Poolable public int currentPlayer; public Date ts; public boolean synched; - public String state; - public String stateH; + public String players; + public String playersH; + public String map; + public String mapH; public String orders; public String ordersH; // diff --git a/core/src/ch/asynk/rustanddust/util/Marshal.java b/core/src/ch/asynk/rustanddust/util/Marshal.java index 513c87b..f805fa1 100644 --- a/core/src/ch/asynk/rustanddust/util/Marshal.java +++ b/core/src/ch/asynk/rustanddust/util/Marshal.java @@ -7,9 +7,9 @@ public interface Marshal { public enum Mode { - FULL, - STATE, - ORDERS + PLAYERS, + MAP, + ORDERS, } public void unload(Mode mode, Json json); diff --git a/tools/sqlite_dumb b/tools/sqlite_dumb index 9e5c5a0..ba1c7db 100755 --- a/tools/sqlite_dumb +++ b/tools/sqlite_dumb @@ -1,6 +1,7 @@ #! /bin/bash -sqlite3 android/assets/data/rustanddust.sqlite 'select state from games order by ts desc limit 1' > state.json +sqlite3 android/assets/data/rustanddust.sqlite 'select players from games order by ts desc limit 1' > players.json +sqlite3 android/assets/data/rustanddust.sqlite 'select map from games order by ts desc limit 1' > map.json sqlite3 android/assets/data/rustanddust.sqlite 'select orders from games order by ts desc limit 1' > orders.json # echo "[" > turns.json # sqlite3 android/assets/data/rustanddust.sqlite 'select payload from turns where game=(select _id from games order by ts desc limit 1) order by _id' | while read rec; do echo "$rec,"; done >> turns.json |