This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
JRummikub/src/jrummikub/control/TurnControl.java
Jannis Harder 2d198820a9 GameControl tests, temporary handler in SettingsControl and small
fixes

git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@288 72836036-5685-4462-b002-a69064685172
2011-05-27 17:54:46 +02:00

574 lines
14 KiB
Java

package jrummikub.control;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import jrummikub.model.Hand;
import jrummikub.model.IHand;
import jrummikub.model.ITable;
import jrummikub.model.Position;
import jrummikub.model.Stone;
import jrummikub.model.StoneColor;
import jrummikub.model.StoneSet;
import jrummikub.util.Connection;
import jrummikub.util.Event;
import jrummikub.util.IEvent;
import jrummikub.util.IListener;
import jrummikub.util.IListener1;
import jrummikub.util.IListener2;
import jrummikub.util.Pair;
import jrummikub.view.IView;
/**
* Controller for a single turn made by a human player
*/
public class TurnControl {
private IHand hand;
private ITable table;
private ITurnTimer timer;
private IView view;
private List<Stone> selectedStones = new ArrayList<Stone>();
private Event endOfTurnEvent = new Event();
private Event redealEvent = new Event();
private List<Connection> connections = new ArrayList<Connection>();
private boolean inspectOnly;
/**
* Create a new TurnControl using a given hand (of the active player), a
* given table and a given view for user interaction.
*
* @param hand
* active player's hand
* @param table
* current table
* @param view
* view for user interaction.
* @param inspectOnly
* the current turn doesn't allow any table manipulation
*/
public TurnControl(IHand hand, ITable table, IView view, boolean inspectOnly) {
this.hand = hand;
this.table = table;
this.view = view;
this.inspectOnly = inspectOnly;
this.timer = new TurnTimer(view);
}
/** Test only constructor **/
TurnControl(IHand hand, ITable table, IView view, ITurnTimer testTimer) {
this.hand = hand;
this.table = table;
this.view = view;
this.timer = testTimer;
this.inspectOnly = false;
}
/**
* Start the turn
*/
public void startTurn() {
IListener endOfTurnListener = new IListener() {
@Override
public void handle() {
endOfTurn(false);
}
};
connections.add(timer.getTimeRunOutEvent().add(endOfTurnListener));
connections.add(view.getPlayerPanel().getEndTurnEvent()
.add(endOfTurnListener));
connections.add(view.getPlayerPanel().getRedealEvent().add(new IListener() {
@Override
public void handle() {
endOfTurn(true);
}
}));
addHandPanelHandlers();
addStoneCollectionHandlers();
if (!inspectOnly)
addTablePanelHandlers();
connections.add(view.getPlayerPanel().getSortByGroupsEvent()
.add(new IListener() {
@Override
public void handle() {
sortByGroups();
}
}));
connections.add(view.getPlayerPanel().getSortByRunsEvent()
.add(new IListener() {
@Override
public void handle() {
sortByRuns();
}
}));
view.getHandPanel().setStones(hand.clone());
view.getHandPanel().resetCurrentRow();
view.enableStartTurnPanel(false);
timer.startTimer();
}
private void addHandPanelHandlers() {
connections.add(view.getHandPanel().getClickEvent()
.add(new IListener1<Position>() {
@Override
public void handle(Position pos) {
handClick(pos);
}
}));
connections.add(view.getHandPanel().getStoneClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
stoneClick(stone, collect);
}
}));
connections.add(view.getHandPanel().getRangeClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
handRangeClick(stone, collect);
}
}));
}
private void addStoneCollectionHandlers() {
connections.add(view.getTablePanel().getStoneCollectionPanel()
.getStoneClickEvent().add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
collectionStoneClick(stone, collect);
}
}));
connections.add(view.getTablePanel().getStoneCollectionPanel()
.getSetClickEvent().add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
collectionSetClick(stone, collect);
}
}));
}
private void addTablePanelHandlers() {
connections.add(view.getTablePanel().getStoneClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
stoneClick(stone, collect);
}
}));
connections.add(view.getTablePanel().getSetClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
tableSetClick(stone, collect);
}
}));
connections.add(view.getTablePanel().getRangeClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override
public void handle(Stone stone, Boolean collect) {
tableRangeClick(stone, collect);
}
}));
connections.add(view.getTablePanel().getClickEvent()
.add(new IListener1<Position>() {
@Override
public void handle(Position pos) {
tableClick(pos);
}
}));
addTablePanelConnectorClickHandlers();
}
private void addTablePanelConnectorClickHandlers() {
connections.add(view.getTablePanel().getLeftConnectorClickEvent()
.add(new IListener1<StoneSet>() {
@Override
public void handle(StoneSet set) {
connectorClick(set, false);
}
}));
connections.add(view.getTablePanel().getRightConnectorClickEvent()
.add(new IListener1<StoneSet>() {
@Override
public void handle(StoneSet set) {
connectorClick(set, true);
}
}));
}
private void handClick(Position pos) {
List<Stone> handStones = new ArrayList<Stone>();
for (Stone s : selectedStones) {
if (hand.pickUp(s)) {
handStones.add(s);
}
}
int i = 0;
for (Stone s : handStones) {
float x = Math.max(0,
Math.min(13, pos.getX() - handStones.size() / 2.0f + i));
hand.drop(s, new Position(x, (float) Math.floor(pos.getY())));
selectedStones.remove(s);
i++;
}
view.setSelectedStones(selectedStones);
view.getHandPanel().setStones(hand);
}
private void sortStones(Comparator<Stone> comparator) {
List<Stone> stones = new ArrayList<Stone>();
for (Pair<Stone, Position> entry : hand) {
stones.add(entry.getFirst());
}
for (Stone stone : stones) {
hand.pickUp(stone);
}
Collections.sort(stones, comparator);
int x = 0, y = 0;
for (Stone stone : stones) {
hand.drop(stone, new Position(x, y));
x++;
if (x >= Hand.WIDTH) {
x = 0;
y++;
}
}
view.getHandPanel().setStones(hand);
}
private void sortByRuns() {
sortStones(new RunComparator());
}
private void sortByGroups() {
sortStones(new GroupComparator());
}
private void stoneClick(Stone stone, boolean collect) {
if (collect) {
if (!selectedStones.remove(stone)) {
selectedStones.add(stone);
}
} else {
selectedStones.clear();
selectedStones.add(stone);
}
view.setSelectedStones(selectedStones);
}
private void collectionStoneClick(Stone stone, boolean collect) {
selectedStones.remove(stone);
if (collect) {
selectedStones.add(stone);
}
view.setSelectedStones(selectedStones);
}
private void collectionSetClick(Stone stone, Boolean collect) {
selectedStones.clear();
view.setSelectedStones(selectedStones);
}
private void pickUpSelectedStones() {
for (Stone stone : selectedStones) {
hand.pickUp(stone);
table.pickUpStone(stone);
}
}
private void tableClick(Position position) {
if (selectedStones.isEmpty()) {
return;
}
pickUpSelectedStones();
table.drop(new StoneSet(selectedStones), new Position(position.getX()
- selectedStones.size() * 0.5f, position.getY() - 0.5f));
selectedStones.clear();
view.getTablePanel().setStoneSets(table);
view.getHandPanel().setStones(hand);
view.setSelectedStones(selectedStones);
}
private void tableSetClick(Stone stone, Boolean collect) {
if (!collect) {
selectedStones.clear();
}
StoneSet selectedSet = table.findStoneSet(stone);
for (Stone setStone : selectedSet) {
selectedStones.remove(setStone);
selectedStones.add(setStone);
}
view.setSelectedStones(selectedStones);
}
private void tableRangeClick(Stone stone, Boolean collect) {
if (selectedStones.isEmpty()) {
stoneClick(stone, true);
return;
}
Stone lastStone = selectedStones.get(selectedStones.size() - 1);
StoneSet lastSet = table.findStoneSet(lastStone);
StoneSet selectedSet = table.findStoneSet(stone);
if (lastSet != selectedSet) {
stoneClick(stone, true);
return;
}
List<Stone> setStones = new ArrayList<Stone>();
for (Stone s : selectedSet) {
setStones.add(s);
}
int firstIndex = setStones.indexOf(lastStone);
int lastIndex = setStones.indexOf(stone);
if (firstIndex > lastIndex) {
int temp = firstIndex;
firstIndex = lastIndex;
lastIndex = temp;
}
for (int i = firstIndex; i <= lastIndex; i++) {
Stone s = setStones.get(i);
selectedStones.remove(s);
selectedStones.add(s);
}
view.setSelectedStones(selectedStones);
}
private void handRangeClick(Stone stone, Boolean collect) {
if (selectedStones.isEmpty()) {
stoneClick(stone, true);
return;
}
Stone lastStone = selectedStones.get(selectedStones.size() - 1);
StoneSet lastSet = table.findStoneSet(lastStone);
if (lastSet != null) {
stoneClick(stone, true);
return;
}
List<Pair<Stone, Position>> handPairs = new ArrayList<Pair<Stone, Position>>();
for (Pair<Stone, Position> entry : hand) {
handPairs.add(entry);
}
Collections.sort(handPairs, new HandStonePositionComparator());
List<Stone> handStones = new ArrayList<Stone>();
for (Pair<Stone, Position> entry : handPairs) {
handStones.add(entry.getFirst());
}
int firstIndex = handStones.indexOf(lastStone);
int lastIndex = handStones.indexOf(stone);
if (firstIndex > lastIndex) {
int temp = firstIndex;
firstIndex = lastIndex;
lastIndex = temp;
}
for (int i = firstIndex; i <= lastIndex; i++) {
Stone s = handStones.get(i);
selectedStones.remove(s);
selectedStones.add(s);
}
view.setSelectedStones(selectedStones);
}
private void connectorClick(StoneSet set, boolean right) {
List<Stone> stones = new LinkedList<Stone>();
Position pos = table.getPosition(set);
for (Stone stone : set) {
stones.add(stone);
}
stones.removeAll(selectedStones);
if (right) {
Collections.reverse(stones);
}
pickUpSelectedStones();
StoneSet newSet = null;
for (Stone stone : stones) {
newSet = table.findStoneSet(stone);
if (newSet != null) {
break;
}
}
if (newSet != null) {
Position newPos = table.getPosition(newSet);
table.pickUp(newSet);
if (right) {
StoneSet joinedSet = newSet.join(new StoneSet(selectedStones));
table.drop(joinedSet, newPos);
} else {
StoneSet joinedSet = new StoneSet(selectedStones).join(newSet);
table.drop(joinedSet, new Position(newPos.getX()
- selectedStones.size(), newPos.getY()));
}
} else {
table.drop(new StoneSet(selectedStones), new Position(pos.getX()
+ (set.size() - selectedStones.size()) * 0.5f, pos.getY()));
}
selectedStones.clear();
view.getTablePanel().setStoneSets(table);
view.getHandPanel().setStones(hand);
view.setSelectedStones(selectedStones);
}
private void endOfTurn(boolean redeal) {
timer.stopTimer();
if (redeal) {
redealEvent.emit();
} else {
endOfTurnEvent.emit();
}
for (Connection c : connections) {
c.remove();
}
view.setSelectedStones(new ArrayList<Stone>());
}
/**
* Get the event that is emitted when the turn is over
*
* @return end of turn event
*/
public IEvent getEndOfTurnEvent() {
return endOfTurnEvent;
}
static private int compareJokers(Stone s1, Stone s2) {
if (!s1.isJoker() && s2.isJoker()) {
return -1;
} else if (s1.isJoker() && !s2.isJoker()) {
return 1;
} else {
return 0;
}
}
static private int compareColors(Stone s1, Stone s2) {
if (s1.getColor() == s2.getColor())
return 0;
for (StoneColor color : StoneColor.values()) {
if (s1.getColor() == color) {
return -1;
} else if (s2.getColor() == color) {
return 1;
}
}
return 0;
}
static private int compareValues(Stone s1, Stone s2) {
if (s1.getValue() < s2.getValue()) {
return -1;
} else if (s1.getValue() > s2.getValue()) {
return 1;
} else {
return 0;
}
}
private static class RunComparator implements Comparator<Stone> {
@Override
public int compare(Stone s1, Stone s2) {
int jokerCompare = compareJokers(s1, s2);
if (jokerCompare != 0) {
return jokerCompare;
}
int colorCompare = compareColors(s1, s2);
if (colorCompare != 0) {
return colorCompare;
}
return compareValues(s1, s2);
}
}
private static class GroupComparator implements Comparator<Stone> {
@Override
public int compare(Stone s1, Stone s2) {
int jokerCompare = compareJokers(s1, s2);
if (jokerCompare != 0) {
return jokerCompare;
}
int valueCompare = compareValues(s1, s2);
if (valueCompare != 0) {
return valueCompare;
}
return compareColors(s1, s2);
}
}
static class HandStonePositionComparator implements
Comparator<Pair<Stone, Position>> {
@Override
public int compare(Pair<Stone, Position> pair1,
Pair<Stone, Position> pair2) {
Position pos1 = pair1.getSecond(), pos2 = pair2.getSecond();
if (pos1.getY() < pos2.getY()) {
return -1;
} else if (pos1.getY() > pos2.getY()) {
return 1;
} else {
if (pos1.getX() < pos2.getX()) {
return -1;
} else if (pos1.getX() > pos2.getX()) {
return 1;
} else {
return 0;
}
}
}
}
/**
* Emitted when the round is aborted and needs to be restarted
*
* @return the event
*/
public Event getRedealEvent() {
return redealEvent;
}
}